serv4rs 0.1.7

serv4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
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)
    }
}

// Actix 提供了两种方法 error_response 和 status_code 来处理错误响应。
// 将在 api 处理程序中使用 Result 返回类型,所以我们需要覆盖 ResponseError Trait。
// Result<HttpResponse, AppError>
impl AppError {
    // we are handling the none. function name should match field name
    fn message(&self) -> String {
        match &*self {
            // Error message is found then clone otherwise default message
            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<validator::ValidationErrors> for AppError {
//     fn from(error: validator::ValidationErrors) -> AppError {
//         AppError {
//             message: None,
//             cause: Some(error.to_string()),
//             error_type: app_error_type::AppErrorType::ValidationError,
//         }
//     }
// }

// 当 QuestString 绑定异常的时候会触发该错误
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,
        }
    }
}

// // 当 RequestBody 不是有效的 json 数据类型时会触发该错误
// impl From<actix_web::error::JsonPayloadError> for AppError {
//     fn from(error: actix_web::error::JsonPayloadError) -> AppError {
//         AppError {
//             message: None,
//             cause: Some(error.to_string()),
//             error_type: app_error_type::AppErrorType::BadRequestError,
//         }
//     }
// }