1use axum::{
2 http::StatusCode,
3 response::{IntoResponse, Response},
4 Json,
5};
6use serde_json::json;
7use thiserror::Error;
8
9#[derive(Error, Debug)]
11pub enum AppError {
12 #[error("内部服务器错误: {0}")]
13 Internal(#[from] anyhow::Error),
14
15 #[error("未找到资源")]
16 NotFound,
17
18 #[error("未授权访问")]
19 Unauthorized,
20
21 #[error("禁止访问")]
22 Forbidden,
23
24 #[error("请求参数错误: {0}")]
25 BadRequest(String),
26
27 #[error("配置错误: {0}")]
28 Config(#[from] config::ConfigError),
29
30 #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
32 #[error("数据库错误: {0}")]
33 Database(#[from] sqlx::Error),
34
35 #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
37 #[error("数据库连接池未初始化")]
38 DatabaseNotInitialized,
39
40 #[cfg(feature = "redis")]
42 #[error("Redis 错误: {0}")]
43 Redis(#[from] redis::RedisError),
44
45 #[cfg(feature = "redis")]
47 #[error("Redis 客户端未初始化")]
48 RedisNotInitialized,
49
50 #[error("业务错误: {1}")]
56 BizError(i32, String),
57
58 #[error("通用错误: {1}")]
64 CommonError(i32, String),
65
66 #[error("自定义错误: {1}")]
72 CustomerError(i32, String),
73
74 #[error("IO 错误: {0}")]
76 Io(#[from] std::io::Error),
77
78 #[error("地址解析错误: {0}")]
80 Addr(#[from] std::net::AddrParseError),
81
82 #[cfg(feature = "redis")]
84 #[error("Redis 连接池错误: {0}")]
85 RedisPool(#[from] deadpool_redis::PoolError),
86
87 #[cfg(feature = "kafka")]
89 #[error("Kafka 错误: {0}")]
90 Kafka(#[from] rdkafka::error::KafkaError),
91}
92
93pub type AppResult<T> = Result<T, AppError>;
95
96impl AppError {
97 pub fn biz_error(status: i32, message: String) -> Self {
113 Self::BizError(status, message)
114 }
115
116 pub fn common_error(status: i32, message: String) -> Self {
132 Self::CommonError(status, message)
133 }
134
135 pub fn customer_error(status: i32, message: String) -> Self {
151 Self::CustomerError(status, message)
152 }
153}
154
155impl IntoResponse for AppError {
156 fn into_response(self) -> Response {
157 let (status, error_message) = match self {
158 AppError::NotFound => (StatusCode::NOT_FOUND, self.to_string()),
159 AppError::Unauthorized => (StatusCode::UNAUTHORIZED, self.to_string()),
160 AppError::Forbidden => (StatusCode::FORBIDDEN, self.to_string()),
161 AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
162 AppError::Config(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
163 #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
164 AppError::Database(e) => {
165 tracing::error!("数据库错误: {:?}", e);
166 (
167 StatusCode::INTERNAL_SERVER_ERROR,
168 format!("数据库错误: {}", e),
169 )
170 }
171 #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
172 AppError::DatabaseNotInitialized => {
173 tracing::error!("数据库连接池未初始化");
174 (
175 StatusCode::INTERNAL_SERVER_ERROR,
176 "数据库连接池未初始化".to_string(),
177 )
178 }
179 #[cfg(feature = "redis")]
180 AppError::Redis(e) => {
181 tracing::error!("Redis 错误: {:?}", e);
182 (
183 StatusCode::INTERNAL_SERVER_ERROR,
184 format!("Redis 错误: {}", e),
185 )
186 }
187 #[cfg(feature = "redis")]
188 AppError::RedisNotInitialized => {
189 tracing::error!("Redis 客户端未初始化");
190 (
191 StatusCode::INTERNAL_SERVER_ERROR,
192 "Redis 客户端未初始化".to_string(),
193 )
194 }
195 AppError::Internal(e) => {
196 tracing::error!("内部错误: {:?}", e);
197 (
198 StatusCode::INTERNAL_SERVER_ERROR,
199 "内部服务器错误".to_string(),
200 )
201 }
202 AppError::BizError(status, msg) => {
203 let msg = format!("业务错误: [{}] {}", status, msg);
204 tracing::warn!(msg);
205 (StatusCode::OK, msg)
206 }
207 AppError::CommonError(status, msg) => {
208 let msg = format!("通用错误: [{}] {}", status, msg);
209 tracing::warn!(msg);
210 (StatusCode::OK, msg)
211 }
212 AppError::CustomerError(status, msg) => {
213 let msg = format!("自定义错误: [{}] {}", status, msg);
214 tracing::warn!(msg);
215 (StatusCode::OK, msg)
216 }
217 AppError::Io(e) => {
218 tracing::error!("IO 错误: {:?}", e);
219 (StatusCode::INTERNAL_SERVER_ERROR, format!("IO 错误: {}", e))
220 }
221 AppError::Addr(e) => {
222 tracing::error!("地址解析错误: {:?}", e);
223 (StatusCode::BAD_REQUEST, format!("地址解析错误: {}", e))
224 }
225 #[cfg(feature = "redis")]
226 AppError::RedisPool(e) => {
227 tracing::error!("Redis 连接池错误: {:?}", e);
228 (
229 StatusCode::INTERNAL_SERVER_ERROR,
230 format!("Redis 连接池错误: {}", e),
231 )
232 }
233 #[cfg(feature = "kafka")]
234 AppError::Kafka(e) => {
235 tracing::error!("Kafka 错误: {:?}", e);
236 (
237 StatusCode::INTERNAL_SERVER_ERROR,
238 format!("Kafka 错误: {}", e),
239 )
240 }
241 };
242
243 let body = Json(json!({
244 "error": error_message,
245 "status": status.as_u16(),
246 }));
247
248 (status, body).into_response()
249 }
250}