fix(openai): /v1/messages端点补齐Codex用量快照提取与错误透传规则
对齐/v1/responses的Forward方法,修复两处不一致: - 成功响应时从响应头提取OAuth账号的Codex使用量数据 - 非failover错误场景下应用管理员配置的错误透传规则
This commit is contained in:
@@ -502,6 +502,11 @@ func (h *OpenAIGatewayHandler) Messages(c *gin.Context) {
|
|||||||
|
|
||||||
setOpsRequestContext(c, reqModel, reqStream, body)
|
setOpsRequestContext(c, reqModel, reqStream, body)
|
||||||
|
|
||||||
|
// 绑定错误透传服务,允许 service 层在非 failover 错误场景复用规则。
|
||||||
|
if h.errorPassthroughService != nil {
|
||||||
|
service.BindErrorPassthroughService(c, h.errorPassthroughService)
|
||||||
|
}
|
||||||
|
|
||||||
subscription, _ := middleware2.GetSubscriptionFromContext(c)
|
subscription, _ := middleware2.GetSubscriptionFromContext(c)
|
||||||
|
|
||||||
service.SetOpsLatencyMs(c, service.OpsAuthLatencyMsKey, time.Since(requestStart).Milliseconds())
|
service.SetOpsLatencyMs(c, service.OpsAuthLatencyMsKey, time.Since(requestStart).Milliseconds())
|
||||||
|
|||||||
@@ -143,14 +143,26 @@ func (s *OpenAIGatewayService) ForwardAsAnthropic(
|
|||||||
return nil, &UpstreamFailoverError{StatusCode: resp.StatusCode, ResponseBody: respBody}
|
return nil, &UpstreamFailoverError{StatusCode: resp.StatusCode, ResponseBody: respBody}
|
||||||
}
|
}
|
||||||
// Non-failover error: return Anthropic-formatted error to client
|
// Non-failover error: return Anthropic-formatted error to client
|
||||||
return s.handleAnthropicErrorResponse(resp, c)
|
return s.handleAnthropicErrorResponse(resp, c, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. Handle normal response
|
// 9. Handle normal response
|
||||||
|
var result *OpenAIForwardResult
|
||||||
|
var handleErr error
|
||||||
if isStream {
|
if isStream {
|
||||||
return s.handleAnthropicStreamingResponse(resp, c, originalModel, mappedModel, startTime)
|
result, handleErr = s.handleAnthropicStreamingResponse(resp, c, originalModel, mappedModel, startTime)
|
||||||
|
} else {
|
||||||
|
result, handleErr = s.handleAnthropicNonStreamingResponse(resp, c, originalModel, mappedModel, startTime)
|
||||||
}
|
}
|
||||||
return s.handleAnthropicNonStreamingResponse(resp, c, originalModel, mappedModel, startTime)
|
|
||||||
|
// Extract and save Codex usage snapshot from response headers (for OAuth accounts)
|
||||||
|
if handleErr == nil && account.Type == AccountTypeOAuth {
|
||||||
|
if snapshot := ParseCodexRateLimitHeaders(resp.Header); snapshot != nil {
|
||||||
|
s.updateCodexUsageSnapshot(ctx, account.ID, snapshot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, handleErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleAnthropicErrorResponse reads an upstream error and returns it in
|
// handleAnthropicErrorResponse reads an upstream error and returns it in
|
||||||
@@ -158,6 +170,7 @@ func (s *OpenAIGatewayService) ForwardAsAnthropic(
|
|||||||
func (s *OpenAIGatewayService) handleAnthropicErrorResponse(
|
func (s *OpenAIGatewayService) handleAnthropicErrorResponse(
|
||||||
resp *http.Response,
|
resp *http.Response,
|
||||||
c *gin.Context,
|
c *gin.Context,
|
||||||
|
account *Account,
|
||||||
) (*OpenAIForwardResult, error) {
|
) (*OpenAIForwardResult, error) {
|
||||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 2<<20))
|
body, _ := io.ReadAll(io.LimitReader(resp.Body, 2<<20))
|
||||||
|
|
||||||
@@ -178,6 +191,21 @@ func (s *OpenAIGatewayService) handleAnthropicErrorResponse(
|
|||||||
}
|
}
|
||||||
setOpsUpstreamError(c, resp.StatusCode, upstreamMsg, upstreamDetail)
|
setOpsUpstreamError(c, resp.StatusCode, upstreamMsg, upstreamDetail)
|
||||||
|
|
||||||
|
// Apply error passthrough rules (matches handleErrorResponse pattern in openai_gateway_service.go)
|
||||||
|
if status, errType, errMsg, matched := applyErrorPassthroughRule(
|
||||||
|
c, account.Platform, resp.StatusCode, body,
|
||||||
|
http.StatusBadGateway, "api_error", "Upstream request failed",
|
||||||
|
); matched {
|
||||||
|
writeAnthropicError(c, status, errType, errMsg)
|
||||||
|
if upstreamMsg == "" {
|
||||||
|
upstreamMsg = errMsg
|
||||||
|
}
|
||||||
|
if upstreamMsg == "" {
|
||||||
|
return nil, fmt.Errorf("upstream error: %d (passthrough rule matched)", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("upstream error: %d (passthrough rule matched) message=%s", resp.StatusCode, upstreamMsg)
|
||||||
|
}
|
||||||
|
|
||||||
errType := "api_error"
|
errType := "api_error"
|
||||||
switch {
|
switch {
|
||||||
case resp.StatusCode == 400:
|
case resp.StatusCode == 400:
|
||||||
|
|||||||
Reference in New Issue
Block a user