Description
In compress.go, brotli.go, and zstd.go, when a response has a body stream and the caller requests compression, the original body stream is wrapped in a NewStreamReader. The compression methods (brotliBody, gzipBody, deflateBody, zstdBody in http.go:1886-2072) only handle io.Closer/ReadCloserWithError on the wrapper, but if the response is discarded before reading, the inner stream is never closed.
// http.go:1886 (brotliBody example)
bs := resp.bodyStream
resp.bodyStream = NewStreamReader(func(w *bufio.Writer) {
// bs is used inside callback, but if callback is never called...
br := acquireBrotliReader(bs)
// ...
})
This is particularly problematic for file-based body streams (e.g., from SendFile).
Impact
- File handle leaks when compressed responses are discarded without reading
- Connection leaks for network-based body streams
Suggested Fix
Ensure Response.Reset() and closeBodyStream() properly cascade Close to inner streams even when the outer stream wrapper was never read.
File
http.go:1886-1901, http.go:1944-1959, http.go:2002-2017, http.go:2057-2072
Description
In
compress.go,brotli.go, andzstd.go, when a response has a body stream and the caller requests compression, the original body stream is wrapped in aNewStreamReader. The compression methods (brotliBody,gzipBody,deflateBody,zstdBodyinhttp.go:1886-2072) only handleio.Closer/ReadCloserWithErroron the wrapper, but if the response is discarded before reading, the inner stream is never closed.This is particularly problematic for file-based body streams (e.g., from
SendFile).Impact
Suggested Fix
Ensure
Response.Reset()andcloseBodyStream()properly cascade Close to inner streams even when the outer stream wrapper was never read.File
http.go:1886-1901,http.go:1944-1959,http.go:2002-2017,http.go:2057-2072