diff --git a/Cargo.lock b/Cargo.lock index 9a06d31d..4e1ad32f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -430,6 +430,7 @@ dependencies = [ "bytes 0.4.12", "chrono", "crypto-mac", + "err-derive", "futures", "futures-util", "garage_model 0.1.1", diff --git a/src/web/error.rs b/src/web/error.rs new file mode 100644 index 00000000..094b22d0 --- /dev/null +++ b/src/web/error.rs @@ -0,0 +1,51 @@ +use err_derive::Error; +use hyper::StatusCode; + +use garage_util::error::Error as GarageError; + +#[derive(Debug, Error)] +pub enum Error { + // Category: internal error + #[error(display = "Internal error: {}", _0)] + InternalError(#[error(source)] GarageError), + + #[error(display = "Internal error (Hyper error): {}", _0)] + Hyper(#[error(source)] hyper::Error), + + #[error(display = "Internal error (HTTP error): {}", _0)] + HTTP(#[error(source)] http::Error), + + // Category: cannot process + #[error(display = "Forbidden: {}", _0)] + Forbidden(String), + + #[error(display = "Not found")] + NotFound, + + // Category: bad request + #[error(display = "Invalid UTF-8: {}", _0)] + InvalidUTF8(#[error(source)] std::str::Utf8Error), + + #[error(display = "Invalid XML: {}", _0)] + InvalidXML(#[error(source)] roxmltree::Error), + + #[error(display = "Invalid header value: {}", _0)] + InvalidHeader(#[error(source)] hyper::header::ToStrError), + + #[error(display = "Bad request: {}", _0)] + BadRequest(String), +} + +impl Error { + pub fn http_status_code(&self) -> StatusCode { + match self { + Error::NotFound => StatusCode::NOT_FOUND, + Error::Forbidden(_) => StatusCode::FORBIDDEN, + Error::InternalError(GarageError::RPC(_)) => StatusCode::SERVICE_UNAVAILABLE, + Error::InternalError(_) | Error::Hyper(_) | Error::HTTP(_) => { + StatusCode::INTERNAL_SERVER_ERROR + } + _ => StatusCode::BAD_REQUEST, + } + } +} diff --git a/src/web/lib.rs b/src/web/lib.rs index c0c668a1..f28937b9 100644 --- a/src/web/lib.rs +++ b/src/web/lib.rs @@ -1,4 +1,6 @@ #[macro_use] extern crate log; +pub mod error; + pub mod web_server; diff --git a/src/web/web_server.rs b/src/web/web_server.rs index 3cc0fa43..4771d209 100644 --- a/src/web/web_server.rs +++ b/src/web/web_server.rs @@ -11,12 +11,13 @@ use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response, Server}; use garage_model::garage::Garage; -use garage_util::error::Error; +use garage_util::error::Error as GarageError; +use crate::error::*; pub async fn run_web_server( garage: Arc, shutdown_signal: impl Future, -) -> Result<(), Error> { +) -> Result<(), GarageError> { let addr = &garage.config.s3_web.bind_addr; let service = make_service_fn(|conn: &AddrStream| {