zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
use actix_web::{http::StatusCode, HttpResponse, ResponseError};

use crate::core::R;

// 全局错误码
pub const UNAUTH_ACCESS: u16 = 401;
pub const INVALID_PARAMS: u16 = 413;
pub const INVALID_REQUEST: u16 = 400;
pub const NOT_FOUND_CODE: u16 = 404;
pub const INTERNAL_SERVER_ERROR: u16 = 500;

#[derive(thiserror::Error)]
pub enum Errors {
    GenericError(String),
    InvalidRequestError(String),
    ValidationError(String),
    InvalidCredentials(String),
    ParseError(String),
    SerdeError(serde_json::Error, Option<String>),
    JwtError(jsonwebtoken::errors::Error, String),
    IOError(String),
    DBError(sqlx::Error, String),
    EsError(String),
    MongoError(anyhow::Error, Option<String>),
    HandlebarError(Option<String>),
    ActixError(actix_web::error::Error, String),
    // WebSocketError(websocket::WebSocketError, Option<String>),
    TungsteniteError(tungstenite::Error, Option<String>),
    NotFound(String),
    // ThrowError(anyhow::Error, Option<String>),
    #[error(transparent)]
    UnexpectedError(#[from] anyhow::Error),
}

impl ResponseError for Errors {
    fn error_response(&self) -> HttpResponse {
        let (code, message) = self.error_message();

        HttpResponse::build(StatusCode::OK)
            .content_type("application/json")
            .body(serde_json::to_string(&R::failed(code, message)).unwrap())
    }
}

impl std::fmt::Debug for Errors {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        crate::commons::error_chain_fmt(self, f)
    }
}

// using `self` as `Display` in `impl Display` will cause infinite recursion
impl std::fmt::Display for Errors {
    fn fmt(&self, _: &mut std::fmt::Formatter) -> std::fmt::Result {
        // write!(f, "{}", self)
        // f.write_str(&self.to_string())?;
        Ok(())
    }
}

impl Errors {
    pub fn error_message(&self) -> (u16, String) {
        match self {
            Errors::GenericError(msg) => {
                log::error!("GenericError: {}", msg);
                (INTERNAL_SERVER_ERROR, msg.to_string())
            }
            Errors::InvalidRequestError(msg) => {
                log::error!("InvalidRequestError: {}", msg);
                (INVALID_REQUEST, msg.to_string())
            }
            Errors::ValidationError(msg) => {
                log::error!("ValidationError: {}", msg);
                (INVALID_REQUEST, msg.to_string())
            }
            Errors::InvalidCredentials(msg) => {
                log::error!("InvalidCredentials: {}", msg);
                (INVALID_REQUEST, "InvalidCredentials error".into())
            }
            Errors::ParseError(msg) => {
                log::error!("ParseError: {}", msg);
                (INTERNAL_SERVER_ERROR, msg.to_string())
            }
            Errors::SerdeError(err, msg) => {
                if let Some(msg) = msg {
                    log::error!("SerdeError: error_message={}, error_details={:?}", msg, err);
                } else {
                    log::error!(
                        "SerdeError: error_message={}, error_details={:?}",
                        "N/a",
                        err
                    );
                }

                (INTERNAL_SERVER_ERROR, "SerdeError error".into())
            }
            Errors::JwtError(err, msg) => {
                log::warn!("JwtError: error_message={}, error_details={:?}", msg, err);
                (UNAUTH_ACCESS, "JwtError error".into())
            }
            Errors::IOError(msg) => {
                log::error!("IOError: {}", msg);
                (INTERNAL_SERVER_ERROR, "IOError error".into())
            }
            Errors::DBError(err, msg) => {
                log::error!("DBError: error_message={}, error_details={:?}", msg, err);
                (INTERNAL_SERVER_ERROR, "DBError error".into())
            }
            Errors::EsError(msg) => {
                log::error!("EsError: error_message={}", msg);
                (INTERNAL_SERVER_ERROR, "EsError error".into())
            }
            Errors::MongoError(err, msg) => {
                if let Some(msg) = msg {
                    log::error!("MongoError: error_message={}, error_details={:?}", msg, err);
                } else {
                    log::error!(
                        "MongoError: error_message={}, error_details={:?}",
                        "N/a",
                        err
                    );
                }

                (INTERNAL_SERVER_ERROR, "MongoError error".into())
            }
            Errors::HandlebarError(msg) => {
                if let Some(msg) = msg {
                    log::error!("HandlebarError: error_message={}", msg);
                } else {
                    log::error!("HandlebarError: error_message={}", "N/a");
                }

                (INTERNAL_SERVER_ERROR, "HandlebarError error".into())
            }
            Errors::ActixError(err, msg) => {
                log::error!("ActixError: error_message={}, error_details={:?}", msg, err);
                (INTERNAL_SERVER_ERROR, "ActixError error".into())
            }
            // Errors::WebSocketError(err, msg) => {
            //     if let Some(msg) = msg {
            //         log::error!(
            //             "WebSocketError: error_message={}, error_details={:?}",
            //             msg,
            //             err
            //         );
            //     } else {
            //         log::error!(
            //             "WebSocketError: error_message={}, error_details={:?}",
            //             "N/a",
            //             err
            //         );
            //     }

            //     (INTERNAL_SERVER_ERROR, "WebSocketError error".into())
            // }
            Errors::TungsteniteError(err, msg) => {
                if let Some(msg) = msg {
                    log::error!(
                        "TungsteniteError: error_message={}, error_details={:?}",
                        msg,
                        err
                    );
                } else {
                    log::error!(
                        "TungsteniteError: error_message={}, error_details={:?}",
                        "N/a",
                        err
                    );
                }

                (INTERNAL_SERVER_ERROR, "TungsteniteError error".into())
            }
            Errors::NotFound(msg) => {
                log::warn!("NotFound: {}", msg);
                (NOT_FOUND_CODE, "NotFound error".into())
            }
            // Errors::ThrowError(err, msg) => {
            //     if let Some(msg) = msg {
            //         log::error!("ThrowError: error_message={}, error_details={:?}", msg, err);
            //     } else {
            //         log::error!(
            //             "ThrowError: error_message={}, error_details={:?}",
            //             "N/a",
            //             err
            //         );
            //     }

            //     (INTERNAL_SERVER_ERROR, "ThrowError error".into())
            // }
            Errors::UnexpectedError(error) => {
                log::error!("UnexpectedError: error_details={:?}", error);
                (
                    INTERNAL_SERVER_ERROR,
                    format!("UnexpectedError: error={:?}", error),
                )
            }
        }
    }
}

impl From<jsonwebtoken::errors::Error> for Errors {
    fn from(err: jsonwebtoken::errors::Error) -> Self {
        let msg = err.to_string();
        Errors::JwtError(err, msg)
    }
}

impl From<actix_web::error::Error> for Errors {
    fn from(err: actix_web::error::Error) -> Self {
        let msg = err.to_string();
        Errors::ActixError(err, msg)
    }
}

impl From<sqlx::Error> for Errors {
    fn from(err: sqlx::Error) -> Self {
        let msg = err.to_string();
        Errors::DBError(err, msg)
    }
}

impl From<serde_json::Error> for Errors {
    fn from(err: serde_json::Error) -> Self {
        let msg = err.to_string();
        Errors::SerdeError(err, Some(msg))
    }
}