fix(reverseproxy): defer response body close to prevent buffer pool memory leaks on early exit paths

This commit is contained in:
Harshal Patel 2026-06-24 16:15:06 +05:30
parent 13a4c3f43c
commit de2aee0d69

View file

@ -1108,6 +1108,13 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origRe
res.Body, _ = h.bufferedBody(res.Body, h.ResponseBuffers)
}
var bodyReleased bool
defer func() {
if !bodyReleased && res != nil && res.Body != nil {
res.Body.Close()
}
}()
// set response placeholders so they can be used in retry match
// expressions and handle_response routes; clear stale header
// placeholders from a previous attempt first so they don't
@ -1139,6 +1146,7 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origRe
}
if match {
res.Body.Close()
bodyReleased = true
return retryableResponseError{
error: fmt.Errorf("upstream response matched retry_match (status %d)", res.StatusCode),
statusCode: res.StatusCode,
@ -1196,6 +1204,7 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origRe
if !hrc.isFinalized {
res.Body.Close()
}
bodyReleased = true
// wrap any route error in roundtripSucceededError so caller knows that
// the roundtrip was successful and to not retry
@ -1209,6 +1218,7 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origRe
}
// copy the response body and headers back to the upstream client
bodyReleased = true
return h.finalizeResponse(rw, req, res, repl, start, logger)
}