use hyper::http::response::Builder; use hyper::StatusCode; use sputnik::hyper_body::FormError; use sputnik::request::QueryError; use sputnik::response::EmptyBuilder; use std::str::Utf8Error; use crate::HyperResponse; /// For convenience this enum also contains nonerroneous variants. pub enum Error { /// A 400 bad request error. BadRequest(String), /// A 401 unauthorized error. Unauthorized(String), /// A 403 forbidden error. Forbidden(String), /// A 404 not found error. NotFound(String), /// A 500 internal server error. Internal(String), /// A 304 response. NotModified, /// A 302 redirect to the given path. Redirect(String), // TODO: use Redirect instead /// Missing trailing slash. MissingTrailingSlash(String), } impl From for Error { fn from(_: Utf8Error) -> Self { Self::BadRequest("invalid UTF-8".into()) } } impl From for Error { fn from(e: git2::Error) -> Self { eprintln!("git error: {}", e); Self::Internal("something went wrong with git".into()) } } impl From for Error { fn from(e: FormError) -> Self { Self::BadRequest(e.to_string()) } } impl From for Error { fn from(e: QueryError) -> Self { Self::BadRequest(e.to_string()) } } impl From for HyperResponse { fn from(err: Error) -> Self { let (status, message) = match err { Error::BadRequest(msg) => (400, msg), Error::Unauthorized(msg) => (401, msg), Error::Forbidden(msg) => (403, msg), Error::NotFound(msg) => (404, msg), Error::Internal(msg) => (500, msg), Error::NotModified => { return Builder::new() .status(StatusCode::NOT_MODIFIED) .empty() .unwrap(); } Error::MissingTrailingSlash(path) => { return Builder::new() .status(StatusCode::FOUND) .header("location", format!("{}/", path)) .body("redirecting".into()) .unwrap(); } Error::Redirect(target) => { return Builder::new() .status(StatusCode::FOUND) .header("location", target) .body("redirecting".into()) .unwrap(); } }; // TODO: use Page Builder::new() .status(status) .header("content-type", "text/html") .body(message.into()) .unwrap() } }