use axum::{ http::StatusCode, response::{IntoResponse, Response}, }; use std::fmt; pub struct Error { inner: anyhow::Error, status: StatusCode, message: String, } impl Error { // Provide a builder method to set the status code pub fn with_status(mut self, status: StatusCode) -> Self { self.status = status; self } // Provide a builder method to set the custom message pub fn with_message(mut self, message: String) -> Self { self.message = message; self } } impl Default for Error { fn default() -> Self { Self { inner: anyhow::Error::new(std::fmt::Error), status: StatusCode::INTERNAL_SERVER_ERROR, message: String::from("An internal error occurred"), } } } impl IntoResponse for Error { fn into_response(self) -> Response { (self.status, format!("{}: {}", self.message, self.inner)).into_response() } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}: {}", self.message, self.inner) } } // make it possible to use ? on anyhow::Error Results impl From for Error { fn from(err: anyhow::Error) -> Self { Self { inner: err, status: StatusCode::INTERNAL_SERVER_ERROR, message: String::from("An unknown internal error occurred"), } } } impl From for Error { fn from(err: minijinja::Error) -> Self { Self { inner: anyhow::Error::new(err), status: StatusCode::INTERNAL_SERVER_ERROR, message: String::from("A Templating Error occured"), } } } #[cfg(test)] mod tests { use super::*; use anyhow::anyhow; use axum::http::StatusCode; #[test] fn test_error_with_status_and_message() { let error = Error::from(anyhow!("Test error")) .with_status(StatusCode::BAD_REQUEST) .with_message(String::from("A custom error message")); assert_eq!(error.status, StatusCode::BAD_REQUEST); assert_eq!(error.message, "A custom error message"); assert_eq!(format!("{}", error.inner), "Test error"); } }