mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
两个 PR 分别合并后在 main 上语义相撞(文本无冲突,CI 才暴露): - #4306 把所有非 failover 透传错误重建为通用净化信封; - #4304 要求确定性 context-window 错误不切号且文案对客户端可见 (如触发客户端自动压缩),其测试断言原文可达。 和解方案(保留双方意图): - 净化器拆出 writeOpenAIPassthroughErrorEnvelope;context-window 错误 仍走本地 JSON 信封 + 净化头策略,但 message 使用脱敏后的上游消息, 不再抹成通用文案;其余错误净化行为不变。 - RebuildsUpstreamErrors 的两个 5xx 用例改用非瞬时状态码(530/501): 瞬时 5xx 对 API-key 账号已按 #4304 契约走 failover(由 APIKeyPassthrough_Transient5xxTriggersFailover 覆盖),净化重建 路径的 5xx 覆盖由非瞬时状态码继续承担。
This commit is contained in:
@@ -517,9 +517,6 @@ func validOpenAIPassthroughRetryAfter(raw string, now time.Time) bool {
|
||||
}
|
||||
|
||||
func writeSanitizedOpenAIPassthroughError(c *gin.Context, upstreamStatus int, upstreamHeaders http.Header) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
downstreamStatus := upstreamStatus
|
||||
message := "Upstream request failed"
|
||||
switch upstreamStatus {
|
||||
@@ -534,6 +531,15 @@ func writeSanitizedOpenAIPassthroughError(c *gin.Context, upstreamStatus int, up
|
||||
message = "Upstream service temporarily unavailable"
|
||||
}
|
||||
}
|
||||
writeOpenAIPassthroughErrorEnvelope(c, downstreamStatus, upstreamHeaders, message)
|
||||
}
|
||||
|
||||
// writeOpenAIPassthroughErrorEnvelope 以本地 JSON 信封 + 净化后的头策略写出
|
||||
// 错误响应;message 由调用方决定(净化通用文案或脱敏后的上游消息)。
|
||||
func writeOpenAIPassthroughErrorEnvelope(c *gin.Context, downstreamStatus int, upstreamHeaders http.Header, message string) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
body, _ := json.Marshal(gin.H{
|
||||
"error": gin.H{
|
||||
"type": "upstream_error",
|
||||
@@ -645,7 +651,14 @@ func (s *OpenAIGatewayService) handleErrorResponsePassthrough(
|
||||
Detail: upstreamDetail,
|
||||
UpstreamResponseBody: upstreamDetail,
|
||||
})
|
||||
writeSanitizedOpenAIPassthroughError(c, resp.StatusCode, resp.Header)
|
||||
// context-window 超限是确定性请求失败(shouldFailoverOpenAIPassthroughResponse
|
||||
// 已保证不切号),其文案对客户端可操作(如触发自动压缩);在净化信封内保留
|
||||
// 脱敏后的上游消息,而不是抹成通用文案。
|
||||
if isOpenAIContextWindowError(upstreamMsg, body) && upstreamMsg != "" {
|
||||
writeOpenAIPassthroughErrorEnvelope(c, resp.StatusCode, resp.Header, upstreamMsg)
|
||||
} else {
|
||||
writeSanitizedOpenAIPassthroughError(c, resp.StatusCode, resp.Header)
|
||||
}
|
||||
|
||||
return fmt.Errorf("upstream error: %d (client response sanitized)", resp.StatusCode)
|
||||
}
|
||||
|
||||
@@ -1049,20 +1049,23 @@ func TestOpenAIGatewayService_APIKeyPassthrough_RebuildsUpstreamErrors(t *testin
|
||||
wantStatus: http.StatusBadGateway,
|
||||
wantMessage: "Upstream authentication failed",
|
||||
},
|
||||
// 瞬时 5xx(500/502/503/504/520-524)对 API-key 账号已改走多账号
|
||||
// failover(见 APIKeyPassthrough_Transient5xxTriggersFailover),此处
|
||||
// 改用非瞬时 5xx 状态码,继续覆盖净化重建路径。
|
||||
{
|
||||
name: "html 5xx",
|
||||
statusCode: http.StatusBadGateway,
|
||||
statusCode: 530,
|
||||
contentType: "text/html; charset=UTF-8",
|
||||
responseBody: `<!DOCTYPE html><title>secret-upstream.example | 502: Bad gateway</title>`,
|
||||
wantStatus: http.StatusBadGateway,
|
||||
responseBody: `<!DOCTYPE html><title>secret-upstream.example | 530: Origin DNS error</title>`,
|
||||
wantStatus: 530,
|
||||
wantMessage: "Upstream service temporarily unavailable",
|
||||
},
|
||||
{
|
||||
name: "structured 5xx",
|
||||
statusCode: http.StatusInternalServerError,
|
||||
statusCode: http.StatusNotImplemented,
|
||||
contentType: "application/json",
|
||||
responseBody: `{"error":{"message":"secret-upstream.example internal failure"}}`,
|
||||
wantStatus: http.StatusInternalServerError,
|
||||
wantStatus: http.StatusNotImplemented,
|
||||
wantMessage: "Upstream service temporarily unavailable",
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user