fix(forwarder): apply responseHeader after body rewrite to fix Content-Type precedence

Response header overrides were applied before rewriteRespBody, so overriding
Content-Type caused the body rewriter to see the override instead of the
original upstream value, breaking the streaming-vs-non-streaming decision.
Move responseHeader and ro.HTTP.Response capture after the body rewrite.
This commit is contained in:
ginuerzh
2026-07-05 19:57:54 +08:00
parent 19be0882db
commit 2baf376c87
+17 -10
View File
@@ -504,18 +504,12 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriteCloser,
}
}
if len(responseHeader) > 0 {
if resp.Header == nil {
resp.Header = http.Header{}
}
for k, v := range responseHeader {
resp.Header.Set(k, v)
}
}
// Reminder: apply responseHeader AFTER body rewrite, not before —
// if responseHeader overrides Content-Type, the rewrite must first
// read the original upstream Content-Type to decide
// streaming vs non-streaming.
ro.HTTP.StatusCode = resp.StatusCode
ro.HTTP.Response.Header = resp.Header.Clone()
ro.HTTP.Response.ContentLength = resp.ContentLength
if log.IsLevelEnabled(logger.TraceLevel) {
dump, _ := httputil.DumpResponse(resp, false)
@@ -553,6 +547,19 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriteCloser,
return
}
// Apply response header overrides after body rewrite so Content-Type
// doesn't affect rewriteRespBody's streaming/non-streaming decision.
if len(responseHeader) > 0 {
if resp.Header == nil {
resp.Header = http.Header{}
}
for k, v := range responseHeader {
resp.Header.Set(k, v)
}
}
ro.HTTP.Response.Header = resp.Header.Clone()
ro.HTTP.Response.ContentLength = resp.ContentLength
if bodySize > 0 {
respBody := xhttp.NewBody(resp.Body, bodySize)
resp.Body = respBody