miniweb/rear/src/service/error.rs

87 lines
2.3 KiB
Rust

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<anyhow::Error> 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<minijinja::Error> 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");
}
}