Skip to content

Commit

Permalink
fix: handle 404 errors, fix error handling for client.resolve (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
yusefnapora committed Sep 22, 2022
1 parent 0337bf2 commit 234ea11
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 17 deletions.
61 changes: 48 additions & 13 deletions w3name-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::{error::Error, fmt::Display, fs, path::PathBuf};
use std::{error::Error, fmt::Display, fs, path::PathBuf, process::exit};

use clap::{Parser, Subcommand};
use error_stack::{IntoReport, Result, ResultExt};
use error_stack::{IntoReport, Result, ResultExt, Report};

use w3name::{Name, Revision, W3NameClient, WritableName};
use w3name::{Name, Revision, W3NameClient, WritableName, error::{ClientError, APIError}};

#[derive(Parser)]
#[clap(name = "w3name", version, about, long_about = None)]
Expand Down Expand Up @@ -49,28 +49,44 @@ async fn main() {
let cli = Cli::parse();

use Commands::*;
match &cli.command {
let res = match &cli.command {
Resolve { name } => {
resolve(name).await.expect("resolve error");
resolve(name).await
}

Publish { key, value } => {
publish(key, value).await.expect("publish error");
publish(key, value).await
}

Create { output } => {
create(output).expect("error creating name");
create(output)
}
};

if let Err(err_report) = res {
eprintln!("{err_report:?}");
exit(1);
}
}

async fn resolve(name_str: &str) -> Result<(), CliError> {
let client = W3NameClient::default();
let name = Name::parse(name_str).change_context(CliError)?;
let revision = client.resolve(&name).await.change_context(CliError)?;
match client.resolve(&name).await {
Ok(revision) => {
println!("{}", revision.value());
Ok(())
}

println!("{}", revision.value());
Ok(())
Err(err_report) => {
if is_404(&err_report) {
eprintln!("no record found for key {}", name_str);
Ok(())
} else {
Err(err_report.change_context(CliError))
}
},
}
}

fn create(output: &Option<PathBuf>) -> Result<(), CliError> {
Expand Down Expand Up @@ -100,8 +116,15 @@ async fn publish(key_file: &PathBuf, value: &str) -> Result<(), CliError> {
let new_revision = match client.resolve(&writable.to_name()).await {
Ok(revision) => revision.increment(value),

// TODO: only fallback to v0 if the name doesn't exist; bail on other errors
Err(_) => Revision::v0(&writable.to_name(), value),
// If the API returned a 404, create the initial (v0) Revision.
// Bail out for all other errors
Err(err_report) => {
if is_404(&err_report) {
Revision::v0(&writable.to_name(), value)
} else {
return Err(err_report.change_context(CliError))
}
},
};

client
Expand All @@ -117,12 +140,24 @@ async fn publish(key_file: &PathBuf, value: &str) -> Result<(), CliError> {
Ok(())
}


/// Returns true if the error report contains an [APIError] with a 404 status
fn is_404(report: &Report<ClientError>) -> bool {
let maybe_api_err: Option<&APIError> = report.downcast_ref();
if let Some(err) = maybe_api_err {
err.status_code == 404
} else {
false
}
}


#[derive(Debug)]
struct CliError;

impl Display for CliError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "error")
write!(f, "something went wrong")
}
}

Expand Down
9 changes: 7 additions & 2 deletions w3name/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ impl W3NameClient {
.change_context(HttpError)
.change_context(ClientError)?;

parse_resolve_response(&name, res).await
if res.status().is_success() {
parse_resolve_response(&name, res).await
} else {
Err(error_from_response(res).await)
}
}
}

Expand Down Expand Up @@ -115,8 +119,9 @@ struct ResolveResponse {
}

async fn error_from_response(res: Response) -> Report<ClientError> {
let status = res.status();
match res.json::<APIErrorResponse>().await {
Ok(json) => report!(APIError(json.message)).change_context(ClientError),
Ok(json) => report!(APIError{ message: json.message, status_code: status }).change_context(ClientError),
Err(e) => report!(e)
.change_context(UnexpectedAPIResponse)
.change_context(ClientError),
Expand Down
7 changes: 5 additions & 2 deletions w3name/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ impl Display for HttpError {
impl Error for HttpError {}

#[derive(Debug)]
pub struct APIError(pub String);
pub struct APIError {
pub message: String,
pub status_code: reqwest::StatusCode,
}

impl Display for APIError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "api error: {}", self.0)
write!(f, "api error: [{}] {}", self.status_code, self.message)
}
}

Expand Down

0 comments on commit 234ea11

Please sign in to comment.