//! 统一错误处理 use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; use axum::Json; use serde_json::json; /// 应用统一错误类型 #[derive(thiserror::Error, Debug)] #[allow(dead_code)] pub enum AppError { #[error("数据库错误: {0}")] Database(#[from] sqlx::Error), #[error("Redis错误: {0}")] Redis(#[from] redis::RedisError), #[error("未找到: {0}")] NotFound(String), #[error("参数错误: {0}")] BadRequest(String), #[error("未授权: {0}")] Unauthorized(String), #[error("无权限: {0}")] Forbidden(String), #[error("请求过于频繁: {0}")] TooManyRequests(String), #[error("内部错误: {0}")] Internal(String), } impl IntoResponse for AppError { fn into_response(self) -> Response { let (status, code, message) = match &self { AppError::Database(e) => { tracing::error!("数据库错误: {}", e); (StatusCode::INTERNAL_SERVER_ERROR, "DATABASE_ERROR", "服务器内部错误") } AppError::Redis(e) => { tracing::error!("Redis错误: {}", e); (StatusCode::INTERNAL_SERVER_ERROR, "REDIS_ERROR", "缓存服务错误") } AppError::NotFound(msg) => (StatusCode::NOT_FOUND, "NOT_FOUND", msg.as_str()), AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, "BAD_REQUEST", msg.as_str()), AppError::Unauthorized(msg) => (StatusCode::UNAUTHORIZED, "UNAUTHORIZED", msg.as_str()), AppError::Forbidden(msg) => (StatusCode::FORBIDDEN, "FORBIDDEN", msg.as_str()), AppError::TooManyRequests(msg) => (StatusCode::TOO_MANY_REQUESTS, "TOO_MANY_REQUESTS", msg.as_str()), AppError::Internal(msg) => { tracing::error!("内部错误: {}", msg); (StatusCode::INTERNAL_SERVER_ERROR, "INTERNAL_ERROR", "服务器内部错误") } }; let body = json!({ "code": code, "message": message, }); (status, Json(body)).into_response() } }