Commit 6ab77f5e authored by erio's avatar erio
Browse files

fix(upstream): passthrough response body directly instead of parsing SSE

ForwardUpstream/ForwardUpstreamGemini should pipe the upstream response
directly to the client (headers + body), not parse it as SSE stream.
parent 4f57d7f7
...@@ -3530,39 +3530,30 @@ func (s *AntigravityGatewayService) ForwardUpstream(ctx context.Context, c *gin. ...@@ -3530,39 +3530,30 @@ func (s *AntigravityGatewayService) ForwardUpstream(ctx context.Context, c *gin.
return nil, s.writeMappedClaudeError(c, account, resp.StatusCode, resp.Header.Get("x-request-id"), respBody) return nil, s.writeMappedClaudeError(c, account, resp.StatusCode, resp.Header.Get("x-request-id"), respBody)
} }
// 成功响应 // 成功响应:透传 response header + body
requestID := resp.Header.Get("x-request-id") requestID := resp.Header.Get("x-request-id")
if requestID != "" {
c.Header("x-request-id", requestID)
}
var usage *ClaudeUsage // 透传上游响应头(排除 hop-by-hop)
var firstTokenMs *int for key, values := range resp.Header {
if claudeReq.Stream { if upstreamHopByHopHeaders[strings.ToLower(key)] {
streamRes, err := s.handleClaudeStreamingResponse(c, resp, startTime, originalModel) continue
if err != nil {
log.Printf("%s status=stream_error error=%v", prefix, err)
return nil, err
} }
usage = streamRes.usage for _, v := range values {
firstTokenMs = streamRes.firstTokenMs c.Header(key, v)
} else {
streamRes, err := s.handleClaudeStreamToNonStreaming(c, resp, startTime, originalModel)
if err != nil {
log.Printf("%s status=stream_collect_error error=%v", prefix, err)
return nil, err
} }
usage = streamRes.usage }
firstTokenMs = streamRes.firstTokenMs
c.Status(resp.StatusCode)
_, copyErr := io.Copy(c.Writer, resp.Body)
if copyErr != nil {
log.Printf("%s status=copy_error error=%v", prefix, copyErr)
} }
return &ForwardResult{ return &ForwardResult{
RequestID: requestID, RequestID: requestID,
Usage: *usage, Model: originalModel,
Model: originalModel, Stream: claudeReq.Stream,
Stream: claudeReq.Stream, Duration: time.Since(startTime),
Duration: time.Since(startTime),
FirstTokenMs: firstTokenMs,
}, nil }, nil
} }
...@@ -3712,35 +3703,23 @@ func (s *AntigravityGatewayService) ForwardUpstreamGemini(ctx context.Context, c ...@@ -3712,35 +3703,23 @@ func (s *AntigravityGatewayService) ForwardUpstreamGemini(ctx context.Context, c
return nil, fmt.Errorf("antigravity upstream error: %d", resp.StatusCode) return nil, fmt.Errorf("antigravity upstream error: %d", resp.StatusCode)
} }
// 成功响应 // 成功响应:透传 response header + body
requestID := resp.Header.Get("x-request-id") requestID := resp.Header.Get("x-request-id")
if requestID != "" {
c.Header("x-request-id", requestID)
}
var usage *ClaudeUsage
var firstTokenMs *int
if stream { // 透传上游响应头(排除 hop-by-hop)
streamRes, err := s.handleGeminiStreamingResponse(c, resp, startTime) for key, values := range resp.Header {
if err != nil { if upstreamHopByHopHeaders[strings.ToLower(key)] {
log.Printf("%s status=stream_error error=%v", prefix, err) continue
return nil, err
} }
usage = streamRes.usage for _, v := range values {
firstTokenMs = streamRes.firstTokenMs c.Header(key, v)
} else {
streamRes, err := s.handleGeminiStreamToNonStreaming(c, resp, startTime)
if err != nil {
log.Printf("%s status=stream_collect_error error=%v", prefix, err)
return nil, err
} }
usage = streamRes.usage
firstTokenMs = streamRes.firstTokenMs
} }
if usage == nil { c.Status(resp.StatusCode)
usage = &ClaudeUsage{} _, copyErr := io.Copy(c.Writer, resp.Body)
if copyErr != nil {
log.Printf("%s status=copy_error error=%v", prefix, copyErr)
} }
imageCount := 0 imageCount := 0
...@@ -3749,13 +3728,11 @@ func (s *AntigravityGatewayService) ForwardUpstreamGemini(ctx context.Context, c ...@@ -3749,13 +3728,11 @@ func (s *AntigravityGatewayService) ForwardUpstreamGemini(ctx context.Context, c
} }
return &ForwardResult{ return &ForwardResult{
RequestID: requestID, RequestID: requestID,
Usage: *usage, Model: originalModel,
Model: originalModel, Stream: stream,
Stream: stream, Duration: time.Since(startTime),
Duration: time.Since(startTime), ImageCount: imageCount,
FirstTokenMs: firstTokenMs, ImageSize: imageSize,
ImageCount: imageCount,
ImageSize: imageSize,
}, nil }, nil
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment