Move things around, improved error handling
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
Alex 2022-05-24 12:31:50 +02:00
parent 7fc9880d72
commit 1b89225c78
Signed by: lx
GPG key ID: 0E496D15096376BE
4 changed files with 50 additions and 11 deletions

View file

@ -23,6 +23,10 @@ garage_util = { path = "../util", optional = true }
[features] [features]
cli = ["clap", "tokio/fs", "tokio/io-std", "garage_util"] cli = ["clap", "tokio/fs", "tokio/io-std", "garage_util"]
[lib]
path = "lib.rs"
[[bin]] [[bin]]
name = "k2v-cli" name = "k2v-cli"
path = "bin/k2v-cli.rs"
required-features = ["cli"] required-features = ["cli"]

View file

@ -5,6 +5,13 @@ use thiserror::Error;
/// Errors returned by this crate /// Errors returned by this crate
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {
#[error("{0} {1}: {2} (at {3})")]
Remote(
http::StatusCode,
Cow<'static, str>,
Cow<'static, str>,
Cow<'static, str>,
),
#[error("received invalid response: {0}")] #[error("received invalid response: {0}")]
InvalidResponse(Cow<'static, str>), InvalidResponse(Cow<'static, str>),
#[error("not found")] #[error("not found")]

View file

@ -311,20 +311,39 @@ impl K2vClient {
StatusCode::NO_CONTENT => Vec::new(), StatusCode::NO_CONTENT => Vec::new(),
StatusCode::NOT_FOUND => return Err(Error::NotFound), StatusCode::NOT_FOUND => return Err(Error::NotFound),
StatusCode::NOT_MODIFIED => Vec::new(), StatusCode::NOT_MODIFIED => Vec::new(),
_ => { s => {
let err_body = read_body(&mut res.headers, res.body) let err_body = read_body(&mut res.headers, res.body)
.await .await
.unwrap_or_default(); .unwrap_or_default();
error!( let err_body_str = std::str::from_utf8(&err_body)
"Error response {}: {}", .map(String::from)
res.status, .unwrap_or_else(|_| base64::encode(&err_body));
std::str::from_utf8(&err_body)
.map(String::from) if s.is_client_error() || s.is_server_error() {
.unwrap_or_else(|_| base64::encode(&err_body)) error!("Error response {}: {}", res.status, err_body_str);
); let err = match serde_json::from_slice::<ErrorResponse>(&err_body) {
return Err(Error::InvalidResponse( Ok(err) => Error::Remote(
format!("invalid error code: {}", res.status).into(), res.status,
)); err.code.into(),
err.message.into(),
err.path.into(),
),
Err(_) => Error::Remote(
res.status,
"unknown".into(),
err_body_str.into(),
"".into(),
),
};
return Err(err);
} else {
let msg = format!(
"Unexpected response code {}. Response body: {}",
res.status, err_body_str
);
error!("{}", msg);
return Err(Error::InvalidResponse(msg.into()));
}
} }
}; };
debug!( debug!(
@ -575,6 +594,15 @@ struct BatchDeleteResponse<'a> {
deleted_items: u64, deleted_items: u64,
} }
#[derive(Deserialize)]
struct ErrorResponse {
code: String,
message: String,
#[allow(dead_code)]
region: String,
path: String,
}
struct Response { struct Response {
body: Vec<u8>, body: Vec<u8>,
status: StatusCode, status: StatusCode,