use axum::{Json, http::StatusCode, response::IntoResponse}; use serde_json::json; use thiserror::Error; pub type Result = std::result::Result; #[derive(Error, Debug)] pub enum AppError { #[error("Configuration error: {0}")] Configuration(String), #[error("Message bus error: {0}")] MessageBus(#[from] async_nats::Error), #[error("Message bus publish error: {0}")] MessageBusPublish(#[from] async_nats::PublishError), #[error("Message bus subscribe error: {0}")] MessageBusSubscribe(String), #[error("Message bus connect error: {0}")] MessageBusConnect(String), #[error("HTTP request to another service failed: {0}")] ServiceRequest(#[from] reqwest::Error), #[error("Bad request: {0}")] BadRequest(String), #[error("Internal error: {0}")] Internal(#[from] anyhow::Error), } impl IntoResponse for AppError { fn into_response(self) -> axum::response::Response { let (status, message) = match &self { AppError::Configuration(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg.clone()), AppError::MessageBus(err) => (StatusCode::SERVICE_UNAVAILABLE, err.to_string()), AppError::MessageBusPublish(err) => (StatusCode::SERVICE_UNAVAILABLE, err.to_string()), AppError::MessageBusSubscribe(msg) => (StatusCode::SERVICE_UNAVAILABLE, msg.clone()), AppError::MessageBusConnect(msg) => (StatusCode::SERVICE_UNAVAILABLE, msg.clone()), AppError::ServiceRequest(err) => (StatusCode::BAD_GATEWAY, err.to_string()), AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg.clone()), AppError::Internal(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()), }; let body = Json(json!({ "error": message })); (status, body).into_response() } } // 手动实现针对 async-nats 泛型错误类型的 From 转换 impl From> for AppError { fn from(err: async_nats::error::Error) -> Self { AppError::MessageBusConnect(err.to_string()) } } impl From for AppError { fn from(err: async_nats::SubscribeError) -> Self { AppError::MessageBusSubscribe(err.to_string()) } }