From 505dbb665b5b6af8a5c135ea3e8a1a532587e02e Mon Sep 17 00:00:00 2001 From: octo-patch Date: Sat, 18 Apr 2026 09:37:54 +0800 Subject: [PATCH] fix: propagate Content-Length header to upstream requests (fixes #2366) When the request body is passed through unchanged (e.g., OpenAI-compatible pass-through mode), Go's http.NewRequest cannot determine the content length and sets ContentLength to -1, resulting in chunked transfer encoding. Some upstream APIs such as Azure's grok model require an explicit Content-Length header and reject chunked requests with a 400 error. Fix: after creating the upstream request, if ContentLength is still -1, inherit it from the original client request. This correctly handles the pass-through case. When the body has been re-serialized (e.g., after ConvertRequest), Go already computes the length from bytes.Buffer and this fallback is not applied. --- relay/adaptor/common.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/relay/adaptor/common.go b/relay/adaptor/common.go index 8953d7a3c8..f7c585934c 100644 --- a/relay/adaptor/common.go +++ b/relay/adaptor/common.go @@ -27,6 +27,13 @@ func DoRequestHelper(a Adaptor, c *gin.Context, meta *meta.Meta, requestBody io. if err != nil { return nil, fmt.Errorf("new request failed: %w", err) } + // When the request body is passed through from the original request (e.g., OpenAI pass-through), + // Go cannot determine the content length and sets it to -1, which causes chunked transfer encoding. + // Some upstream APIs (e.g., Azure grok models) require an explicit Content-Length header. + // Inherit the content length from the original request as a fallback. + if req.ContentLength == -1 { + req.ContentLength = c.Request.ContentLength + } err = a.SetupRequestHeader(c, req, meta) if err != nil { return nil, fmt.Errorf("setup request header failed: %w", err)