//! 统一错误类型,序列化为跨语言契约约定的结构。 //! 约定见 docs/architecture/service-boundaries.md 第 7 节。 use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; use axum::Json; use serde_json::json; pub enum ApiError { /// 请求参数不合法(4xx)。 BadRequest(String), /// 未授权:授权凭证缺失 / 过期 / 签名无效,或请求内容与凭证 body_hash 不匹配(401)。 Unauthorized(String), /// 资源不存在,例如取消一个未知或已完成的任务(404)。 NotFound(String), /// 服务暂不可用,例如并发闸耗尽或容器资源不足(503)。 Unavailable(String), /// 执行失败或内部错误(500)。 Internal(String), } impl IntoResponse for ApiError { fn into_response(self) -> Response { let (code, message, status) = match self { ApiError::BadRequest(m) => ("bad_request", m, StatusCode::BAD_REQUEST), ApiError::Unauthorized(m) => { ("sandbox_unauthorized", m, StatusCode::UNAUTHORIZED) } ApiError::NotFound(m) => ("not_found", m, StatusCode::NOT_FOUND), ApiError::Unavailable(m) => { ("service_unavailable", m, StatusCode::SERVICE_UNAVAILABLE) } ApiError::Internal(m) => ("exec_failed", m, StatusCode::INTERNAL_SERVER_ERROR), }; let body = Json(json!({ "error": { "code": code, "message": message } })); (status, body).into_response() } }