inspirer_foundation/
error.rs1#[cfg(feature = "enable-axum")]
2use axum::{http::StatusCode, response::IntoResponse, Json};
3use serde::Serialize;
4use std::fmt::{self, Debug, Display};
5
6pub type Result<T, E = Error> = std::result::Result<T, E>;
7
8#[derive(Debug, Serialize)]
10pub struct ErrorMessage<S, T = ()>
11where
12 S: Display + Debug,
13 T: Serialize + Debug,
14{
15 #[serde(skip)]
16 pub status: StatusCode,
17 pub code: u32,
18 pub msg: S,
19 pub data: T,
20}
21
22pub type ErrorMessageTemplate = ErrorMessage<&'static str, ()>;
24
25impl<S, T> std::error::Error for ErrorMessage<S, T>
26where
27 S: Serialize + Display + Debug,
28 T: Serialize + Debug,
29{
30}
31
32impl<S, T> fmt::Display for ErrorMessage<S, T>
33where
34 S: Serialize + Display + Debug,
35 T: Serialize + Debug,
36{
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 write!(f, "{}", self.msg)
39 }
40}
41
42impl<S, T> IntoResponse for ErrorMessage<S, T>
43where
44 S: Serialize + Display + Debug,
45 T: Serialize + Debug,
46{
47 fn into_response(self) -> axum::response::Response {
48 (self.status, Json(self)).into_response()
49 }
50}
51
52#[macro_export]
53macro_rules! define_inspirer_error {
54 ($name:ident, $status:expr, $code:literal, $msg:literal) => {
55 pub const $name: $crate::ErrorMessageTemplate = ErrorMessageTemplate { status: $status, code: $code, msg: $msg, data: () };
56 };
57}
58
59define_inspirer_error!(UNKONWN_ERROR, StatusCode::INTERNAL_SERVER_ERROR, 1, "System internal error.");
60
61#[derive(Debug, thiserror::Error)]
62pub enum Error {
63 #[error("Extract Service extension error.")]
64 ExtractServiceExtensionFailed,
65 #[error("Get configuration data failed.")]
66 GetConfigurationFailedError,
67 #[error("Get configuration component failed.")]
68 GetConfigurationComponentFailed,
69 #[error(transparent)]
70 ConfigError(#[from] config::ConfigError),
71 #[error(transparent)]
72 DatabaseError(#[from] sea_orm::DbErr),
73 #[error(transparent)]
74 InspirerWebApplicationErrorMessage(#[from] ErrorMessageTemplate),
75 #[error(transparent)]
76 ValidateError(#[from] validator::ValidationErrors),
77 #[error(transparent)]
78 AxumJsonRejection(#[from] axum::extract::rejection::JsonRejection),
79 #[error(transparent)]
80 AxumFormRejection(#[from] axum::extract::rejection::FormRejection),
81 #[error(transparent)]
82 AxumQueryRejection(#[from] axum::extract::rejection::QueryRejection),
83 #[error("System internal error.")]
84 UnknownError,
85}
86
87#[cfg(feature = "enable-axum")]
88impl IntoResponse for Error {
89 fn into_response(self) -> axum::response::Response {
90 let (code, status) = match self {
91 Self::UnknownError => (1, StatusCode::INTERNAL_SERVER_ERROR),
92 Self::ExtractServiceExtensionFailed => (2, StatusCode::INTERNAL_SERVER_ERROR),
93 Self::GetConfigurationFailedError => (3, StatusCode::INTERNAL_SERVER_ERROR),
94 Self::GetConfigurationComponentFailed => (4, StatusCode::INTERNAL_SERVER_ERROR),
95 Self::ConfigError(_) => (5, StatusCode::INTERNAL_SERVER_ERROR),
96 Self::DatabaseError(_) => (6, StatusCode::INTERNAL_SERVER_ERROR),
97 Self::AxumFormRejection(_)
98 | Self::AxumJsonRejection(_)
99 | Self::AxumQueryRejection(_) => {
100 return ErrorMessage {
101 code: 7,
102 msg: "请求参数解析错误",
103 data: Option::<()>::None,
104 status: StatusCode::BAD_REQUEST,
105 }
106 .into_response();
107 }
108 Self::ValidateError(err) => {
109 return ErrorMessage {
110 code: 8,
111 msg: "请求参数错误",
112 data: err.errors(),
113 status: StatusCode::BAD_REQUEST,
114 }
115 .into_response();
116 }
117 Self::InspirerWebApplicationErrorMessage(msg) => return msg.into_response(),
118 };
119
120 ErrorMessage {
121 status,
122 code,
123 msg: format!("{}", self),
124 data: Option::<()>::None,
125 }
126 .into_response()
127 }
128}