use crate::errors::app_error_type;
use crate::R;
use actix_web::{error::ResponseError, http::StatusCode, HttpResponse};
use std::fmt;
static UNEXPECTED_MESSAGE: &str = "An unexpected error has occured";
#[derive(Debug)]
pub struct AppError {
pub cause: Option<String>,
pub message: Option<String>,
pub error_type: app_error_type::AppErrorType,
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl AppError {
fn message(&self) -> String {
match &*self {
AppError {
cause: _,
message: Some(message),
error_type: _,
} => message.clone(),
AppError {
cause: Some(_),
message: None,
error_type: app_error_type::AppErrorType::DbError,
} => "Database error".to_string(),
AppError {
cause: Some(cause),
message: None,
error_type: app_error_type::AppErrorType::BadRequestError,
} => cause.clone(),
AppError {
cause: Some(cause),
message: None,
error_type: app_error_type::AppErrorType::ValidationError,
} => cause.clone(),
_ => UNEXPECTED_MESSAGE.to_string(),
}
}
fn code(&self) -> u16 {
match self.error_type {
app_error_type::AppErrorType::DbError => 500,
app_error_type::AppErrorType::BadRequestError => 400,
app_error_type::AppErrorType::ValidationError => 413,
}
}
fn print_error_message_log(&self) -> String {
let error_message = self.message();
log::error!(
"ResponseError: error_type={}, code={}, error_message={}, cause={}",
self.error_type,
self.code(),
error_message,
if let Some(c) = &self.cause {
c.clone()
} else {
"N/a".to_string()
}
);
error_message
}
}
impl ResponseError for AppError {
fn error_response(&self) -> HttpResponse {
HttpResponse::build(StatusCode::OK).json(R::<String>::failed(
self.code(),
self.print_error_message_log(),
))
}
}
impl From<actix_web::error::Error> for AppError {
fn from(error: actix_web::error::Error) -> AppError {
AppError {
message: None,
cause: Some(error.to_string()),
error_type: app_error_type::AppErrorType::BadRequestError,
}
}
}