use actix_web::{http::StatusCode, HttpResponse, ResponseError}; use diesel::result::Error; use serde::Serialize; use std::fmt::{Debug, Display, Formatter, Result}; #[derive(Debug)] pub struct ErrorResponse { pub message: String, pub status: StatusCode, } impl ErrorResponse { pub fn new(message: &str, status: StatusCode) -> Self { ErrorResponse { message: message.to_string(), status, } } } impl Display for ErrorResponse { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "{}: {}", self.status, self.message) } } impl From for ErrorResponse { fn from(err: actix_web::Error) -> Self { ErrorResponse { status: err.error_response().status(), message: err.to_string(), } } } impl From for ErrorResponse { fn from(err: Error) -> Self { match err { Error::NotFound => ErrorResponse { status: StatusCode::NOT_FOUND, message: err.to_string(), }, _ => ErrorResponse { status: StatusCode::INTERNAL_SERVER_ERROR, message: err.to_string(), }, } } } impl ResponseError for ErrorResponse { fn status_code(&self) -> StatusCode { self.status } fn error_response(&self) -> HttpResponse { #[derive(Serialize)] struct Response { error: ErrorResponse, } #[derive(Serialize)] struct ErrorResponse { message: String, status: u16, } HttpResponse::build(self.status_code()) .content_type("application/json") .json(Response { error: ErrorResponse { message: self.message.to_string(), status: self.status_code().as_u16(), }, }) } }