39 lines
1.5 KiB
Rust
39 lines
1.5 KiB
Rust
//! 统一错误类型,序列化为跨语言契约约定的结构。
|
|
//! 约定见 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()
|
|
}
|
|
}
|