Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add api types crate & update apiclient errors #4040

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
apiclient: updated errors to match client errors
  • Loading branch information
sumukhballal committed Jun 18, 2024
commit b2acf48316b7ee03fe854c49da01299c6c62fe43
61 changes: 49 additions & 12 deletions sources/api/apiclient/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 47,10 @@ mod error {
body: String,
},

// This type of error just returns the source.
#[snafu(display("{}", body))]
Raw { body: String },

#[snafu(display("Failed to read body of response: {}", source))]
ResponseBodyRead { source: hyper::Error },

Expand Down Expand Up @@ -84,18 88,7 @@ where
S2: AsRef<str>,
{
let (status, body) = raw_request_unchecked(&socket_path, &uri, &method, data).await?;

// Error if the response status is in not in the 2xx range.
ensure!(
status.is_success(),
error::ResponseStatusSnafu {
method: method.as_ref(),
code: status,
uri: uri.as_ref(),
body,
}
);

check_invalid_client_input(body.as_ref(), status, method.as_ref(), uri.as_ref())?;
Ok((status, body))
}

Expand Down Expand Up @@ -156,6 149,50 @@ pub(crate) fn rando() -> String {
.collect()
}

/// Different Client type errors we expect.
const CLIENT_DESERIALIZATION_MAP_ERROR: &str = "Unable to match your input to the data model. We may not have enough type information. Please try the --json input form";
const CLIENT_DESERIALIZATION_JSON_ERROR: &str = "Unable to deserialize input JSON into model";
const SERVER_DESERIALIZATION_JSON_ERROR: &str = "Json deserialize error";
const CLIENT_SERIALIZATION_ERROR: &str = "Unable to serialize data";

#[derive(Debug)]
enum ClientTypeErrors {}

impl ClientTypeErrors {
fn from(input: &str) -> Option<&str> {
if input.contains(CLIENT_DESERIALIZATION_JSON_ERROR)
|| input.contains(CLIENT_DESERIALIZATION_MAP_ERROR)
|| input.contains(SERVER_DESERIALIZATION_JSON_ERROR)
|| input.contains(CLIENT_SERIALIZATION_ERROR)
{
Some("client_error")
} else {
None
}
}
}
sumukhballal marked this conversation as resolved.
Show resolved Hide resolved

fn check_invalid_client_input(
body: &str,
status: http::StatusCode,
method: &str,
uri: &str,
) -> Result<()> {
match ClientTypeErrors::from(body) {
Some(_) => ensure!(status.is_success(), error::RawSnafu { body }),
None => ensure!(
status.is_success(),
error::ResponseStatusSnafu {
method: method.to_string(),
code: status,
uri: uri.to_string(),
body,
}
),
};
Ok(())
}

/// Different input types supported by the Settings API.
#[derive(Debug)]
pub enum SettingsInput {
Expand Down
14 changes: 13 additions & 1 deletion sources/api/apiclient/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 778,12 @@ async fn run() -> Result<()> {

set::set(&args.socket_path, settings)
.await
.context(error::SetSnafu)?;
.map_err(|e| match e {
set::Error::Raw { source: _ } => error::Error::Raw {
source: Box::new(e),
},
_ => error::Error::Set { source: e },
})?;
}

Subcommand::Update(subcommand) => match subcommand {
Expand Down Expand Up @@ -905,6 910,12 @@ mod error {
source: Box<apiclient::Error>,
},

// This type of error just returns the source.
#[snafu(display("{}", source))]
Raw {
#[snafu(source(from(apiclient::set::Error, Box::new)))]
source: Box<apiclient::set::Error>,
},
#[snafu(display("Failed to get report: {}", source))]
Report { source: report::Error },

Expand All @@ -924,4 935,5 @@ mod error {
UpdateCheck { source: update::Error },
}
}

type Result<T> = std::result::Result<T, error::Error>;
18 changes: 17 additions & 1 deletion sources/api/apiclient/src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 21,16 @@ where
let method = "PATCH";
let (_status, _body) = crate::raw_request(&socket_path, &uri, method, Some(settings_data))
.await
.context(error::RequestSnafu { uri, method })?;
.map_err(|e| match e {
crate::Error::Raw { body } => Error::Raw {
source: Box::new(crate::Error::Raw { body }),
},
_ => Error::Request {
method: method.to_string(),
uri,
source: Box::new(e),
},
})?;

// Commit the transaction and apply it to the system.
let uri = format!("/tx/commit_and_apply?tx={}", transaction);
Expand Down Expand Up @@ -49,6 58,13 @@ mod error {
#[snafu(source(from(crate::Error, Box::new)))]
source: Box<crate::Error>,
},

// This type of error just returns the source.
#[snafu(display("{}", source))]
Raw {
#[snafu(source(from(crate::Error, Box::new)))]
source: Box<crate::Error>,
},
}
}
pub use error::Error;
Expand Down