Spaces:
Sleeping
Sleeping
File size: 4,691 Bytes
69f686e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | //! HTTP 错误响应格式 —— 支持 OpenAI 与 Anthropic 兼容错误 JSON
//!
//! 将适配器错误映射为标准错误响应格式。
use axum::{
Json,
http::{HeaderValue, StatusCode, header},
response::{IntoResponse, Response},
};
use serde::Serialize;
use std::fmt;
use crate::anthropic_compat::AnthropicCompatError;
use crate::openai_adapter::OpenAIAdapterError;
/// OpenAI 兼容错误响应体
#[derive(Debug, Serialize)]
pub struct OpenAIErrorBody {
error: OpenAIErrorDetail,
}
#[derive(Debug, Serialize)]
struct OpenAIErrorDetail {
message: String,
#[serde(rename = "type")]
error_type: &'static str,
code: &'static str,
}
/// Anthropic 兼容错误响应体
#[derive(Debug, Serialize)]
pub struct AnthropicErrorBody {
#[serde(rename = "type")]
error_type: &'static str,
message: String,
}
/// 服务器层错误类型
#[derive(Debug)]
pub enum ServerError {
/// OpenAI 适配器错误
Adapter(OpenAIAdapterError),
/// Anthropic 兼容层错误
Anthropic(AnthropicCompatError),
/// 未授权(无效 API token)
Unauthorized,
/// 资源不存在
NotFound(String),
}
impl fmt::Display for ServerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Adapter(e) => write!(f, "{}", e),
Self::Anthropic(e) => write!(f, "{}", e),
Self::Unauthorized => write!(f, "invalid api token"),
Self::NotFound(id) => write!(f, "模型 '{}' 不存在", id),
}
}
}
impl From<OpenAIAdapterError> for ServerError {
fn from(e: OpenAIAdapterError) -> Self {
Self::Adapter(e)
}
}
impl From<AnthropicCompatError> for ServerError {
fn from(e: AnthropicCompatError) -> Self {
Self::Anthropic(e)
}
}
impl IntoResponse for ServerError {
fn into_response(self) -> Response {
match &self {
Self::Anthropic(e) => anthropic_error_response(e),
_ => openai_error_response(&self),
}
}
}
fn openai_error_response(err: &ServerError) -> Response {
let (status, error_type, code) = match err {
ServerError::Adapter(e) => {
let status =
StatusCode::from_u16(e.status_code()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
let (error_type, code) = match e {
OpenAIAdapterError::BadRequest(_) => ("invalid_request_error", "bad_request"),
OpenAIAdapterError::Overloaded => ("server_error", "overloaded"),
OpenAIAdapterError::ProviderError(_) => ("server_error", "provider_error"),
OpenAIAdapterError::Internal(_) | OpenAIAdapterError::ToolCallRepairNeeded(_) => {
("server_error", "internal_error")
}
};
(status, error_type, code)
}
ServerError::Unauthorized => (
StatusCode::UNAUTHORIZED,
"authentication_error",
"invalid_api_token",
),
ServerError::NotFound(_) => (
StatusCode::NOT_FOUND,
"invalid_request_error",
"model_not_found",
),
// Anthropic 错误不会走到这里
ServerError::Anthropic(_) => (
StatusCode::INTERNAL_SERVER_ERROR,
"server_error",
"internal_error",
),
};
let body = OpenAIErrorBody {
error: OpenAIErrorDetail {
message: err.to_string(),
error_type,
code,
},
};
log::debug!(target: "http::response", "{} error: {}", status, body.error.message);
let mut resp = (status, Json(body)).into_response();
if status == StatusCode::TOO_MANY_REQUESTS {
resp.headers_mut()
.insert(header::RETRY_AFTER, HeaderValue::from_static("30"));
}
resp
}
fn anthropic_error_response(err: &AnthropicCompatError) -> Response {
let status =
StatusCode::from_u16(err.status_code()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
let error_type = match err {
AnthropicCompatError::BadRequest(_) => "invalid_request_error",
AnthropicCompatError::Overloaded => "overloaded_error",
AnthropicCompatError::Internal(_) => "api_error",
};
let body = AnthropicErrorBody {
error_type,
message: err.to_string(),
};
log::debug!(target: "http::response", "{} Anthropic error: {}", status, body.message);
let mut resp = (status, Json(body)).into_response();
if status == StatusCode::TOO_MANY_REQUESTS {
resp.headers_mut()
.insert(header::RETRY_AFTER, HeaderValue::from_static("30"));
}
resp
}
|