K2V client improvements #307
4 changed files with 50 additions and 11 deletions
|
@ -23,6 +23,10 @@ garage_util = { path = "../util", optional = true }
|
|||
[features]
|
||||
cli = ["clap", "tokio/fs", "tokio/io-std", "garage_util"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "k2v-cli"
|
||||
path = "bin/k2v-cli.rs"
|
||||
required-features = ["cli"]
|
||||
|
|
|
@ -5,6 +5,13 @@ use thiserror::Error;
|
|||
/// Errors returned by this crate
|
||||
#[derive(Error, Debug)]
|
||||
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}")]
|
||||
InvalidResponse(Cow<'static, str>),
|
||||
#[error("not found")]
|
|
@ -311,20 +311,39 @@ impl K2vClient {
|
|||
StatusCode::NO_CONTENT => Vec::new(),
|
||||
StatusCode::NOT_FOUND => return Err(Error::NotFound),
|
||||
StatusCode::NOT_MODIFIED => Vec::new(),
|
||||
_ => {
|
||||
s => {
|
||||
let err_body = read_body(&mut res.headers, res.body)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
error!(
|
||||
"Error response {}: {}",
|
||||
res.status,
|
||||
std::str::from_utf8(&err_body)
|
||||
.map(String::from)
|
||||
.unwrap_or_else(|_| base64::encode(&err_body))
|
||||
);
|
||||
return Err(Error::InvalidResponse(
|
||||
format!("invalid error code: {}", res.status).into(),
|
||||
));
|
||||
let err_body_str = std::str::from_utf8(&err_body)
|
||||
.map(String::from)
|
||||
.unwrap_or_else(|_| base64::encode(&err_body));
|
||||
|
||||
if s.is_client_error() || s.is_server_error() {
|
||||
error!("Error response {}: {}", res.status, err_body_str);
|
||||
let err = match serde_json::from_slice::<ErrorResponse>(&err_body) {
|
||||
Ok(err) => Error::Remote(
|
||||
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!(
|
||||
|
@ -575,6 +594,15 @@ struct BatchDeleteResponse<'a> {
|
|||
deleted_items: u64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ErrorResponse {
|
||||
code: String,
|
||||
message: String,
|
||||
#[allow(dead_code)]
|
||||
region: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
struct Response {
|
||||
body: Vec<u8>,
|
||||
status: StatusCode,
|
Loading…
Reference in a new issue