daoyi_cloud_common/
error.rs

1use salvo::http::{ParseError, StatusCode, StatusError};
2use salvo::oapi::{self, EndpointOutRegister, ToSchema};
3use salvo::prelude::*;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum AppError {
8    #[error("public: `{0}`")]
9    Public(String),
10    #[error("internal: `{0}`")]
11    Internal(String),
12    #[error("salvo internal error: `{0}`")]
13    Salvo(#[from] ::salvo::Error),
14    #[error("http status error: `{0}`")]
15    HttpStatus(#[from] StatusError),
16    #[error("http parse error:`{0}`")]
17    HttpParse(#[from] ParseError),
18    #[error("anyhow error:`{0}`")]
19    Anyhow(#[from] anyhow::Error),
20    #[error("rbatis::Error:`{0}`")]
21    Rbatis(#[from] rbatis::Error),
22    #[error("validation error:`{0}`")]
23    Validation(#[from] validator::ValidationErrors),
24}
25impl AppError {
26    pub fn public<S: Into<String>>(msg: S) -> Self {
27        Self::Public(msg.into())
28    }
29
30    pub fn internal<S: Into<String>>(msg: S) -> Self {
31        Self::Internal(msg.into())
32    }
33}
34
35#[async_trait]
36impl Writer for AppError {
37    async fn write(mut self, _req: &mut Request, _depot: &mut Depot, res: &mut Response) {
38        let code = match &self {
39            Self::HttpStatus(e) => e.code,
40            _ => StatusCode::INTERNAL_SERVER_ERROR,
41        };
42        res.status_code(code);
43        let data = match self {
44            Self::Salvo(e) => {
45                tracing::error!(error = ?e, "salvo error");
46                StatusError::internal_server_error().brief("Unknown error happened in salvo.")
47            }
48            Self::Public(msg) => StatusError::internal_server_error().brief(msg),
49            Self::Internal(msg) => {
50                tracing::error!(msg = msg, "internal error");
51                StatusError::internal_server_error()
52            }
53            Self::HttpStatus(e) => e,
54            e => StatusError::internal_server_error()
55                .brief(format!("Unknown error happened: {e}"))
56                .cause(e),
57        };
58        res.render(data);
59    }
60}
61impl EndpointOutRegister for AppError {
62    fn register(components: &mut salvo::oapi::Components, operation: &mut salvo::oapi::Operation) {
63        operation.responses.insert(
64            StatusCode::INTERNAL_SERVER_ERROR.as_str(),
65            oapi::Response::new("Internal server error")
66                .add_content("application/json", StatusError::to_schema(components)),
67        );
68        operation.responses.insert(
69            StatusCode::NOT_FOUND.as_str(),
70            oapi::Response::new("Not found")
71                .add_content("application/json", StatusError::to_schema(components)),
72        );
73        operation.responses.insert(
74            StatusCode::BAD_REQUEST.as_str(),
75            oapi::Response::new("Bad request")
76                .add_content("application/json", StatusError::to_schema(components)),
77        );
78    }
79}