use snafu::Snafu;
#[derive(Debug, Snafu)]
pub enum RestError {
#[snafu(display("Bad request: {}", message))]
BadRequest { message: String },
#[snafu(display("Not authorized: {}", message))]
NotAuthorized { message: String },
#[snafu(display("Forbidden: {}", message))]
Forbidden { message: String },
#[snafu(display(
"Resource not found: {:?} named {:?}: {}",
resource_type,
resource_name,
message
))]
NoSuchResource {
resource_type: Option<String>,
resource_name: Option<String>,
message: String,
},
#[snafu(display(
"Resource already exists: {:?} named {:?}: {}",
resource_type,
resource_name,
message
))]
AlreadyExists {
resource_type: Option<String>,
resource_name: Option<String>,
message: String,
},
#[snafu(display("Service failure: {}", message))]
ServiceFailure { message: String },
#[snafu(display("Not implemented: {}", message))]
NotImplemented { message: String },
#[snafu(display("Service unavailable: {}", message))]
ServiceUnavailable { message: String },
#[snafu(display("Unexpected error: {}", message))]
Unexpected { message: String },
}
use super::api_response::ErrorResponse;
impl RestError {
pub fn parse_error_response(text: &str, status_code: u16) -> ErrorResponse {
if let Ok(error) = serde_json::from_str::<ErrorResponse>(text) {
if error.message.is_some() {
return error;
}
return ErrorResponse::new(
error.resource_type,
error.resource_name,
Some(text.to_string()),
error.code.or(Some(status_code as i32)),
);
}
ErrorResponse::new(
None,
None,
Some(if text.is_empty() {
"response body is null".to_string()
} else {
text.to_string()
}),
Some(status_code as i32),
)
}
pub fn from_error_response(error: ErrorResponse) -> Self {
let code = error.code.unwrap_or(500);
let message = error
.message
.clone()
.unwrap_or_else(|| "Unknown error".to_string());
match code {
400 => RestError::BadRequest { message },
401 => RestError::NotAuthorized { message },
403 => RestError::Forbidden { message },
404 => RestError::NoSuchResource {
resource_type: error.resource_type,
resource_name: error.resource_name,
message,
},
409 => RestError::AlreadyExists {
resource_type: error.resource_type,
resource_name: error.resource_name,
message,
},
500 => RestError::ServiceFailure { message },
501 => RestError::NotImplemented { message },
503 => RestError::ServiceUnavailable { message },
_ => RestError::Unexpected { message },
}
}
}