From a155ad55a35a527d4980d91e1619ccad659d3bc8 Mon Sep 17 00:00:00 2001 From: Joshua Rogers Date: Sun, 21 Dec 2025 17:15:35 +0800 Subject: [PATCH] httputil: add Vary: Accept-Encoding and fix compression headers (#17466) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Emit `Vary: Accept-Encoding` in newCompressedResponseWriter so shared caches key responses by content-coding. This prevents cache poisoning and undecodable bytes when a compressed variant is cached and later served to a client that didn't advertise support. (RFC 9110 §12.5.5 "Vary"; RFC 9111 §4.1 cache key & Vary) - When selecting gzip/deflate, set `Content-Encoding` and delete any existing `Content-Length` so Go's net/http can frame the message correctly (chunked for HTTP/1.1; implicit for HTTP/2+). This avoids stale length mismatches and related proxy/client issues. Signed-off-by: Joshua Rogers --- util/httputil/compression.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/util/httputil/compression.go b/util/httputil/compression.go index d5bedb7fa9..e67f9ffd9f 100644 --- a/util/httputil/compression.go +++ b/util/httputil/compression.go @@ -56,6 +56,7 @@ func (c *compressedResponseWriter) Close() { // Constructs a new compressedResponseWriter based on client request headers. func newCompressedResponseWriter(writer http.ResponseWriter, req *http.Request) *compressedResponseWriter { + writer.Header().Add("Vary", acceptEncodingHeader) raw := req.Header.Get(acceptEncodingHeader) var ( encoding string @@ -65,13 +66,17 @@ func newCompressedResponseWriter(writer http.ResponseWriter, req *http.Request) encoding, raw, commaFound = strings.Cut(raw, ",") switch strings.TrimSpace(encoding) { case gzipEncoding: - writer.Header().Set(contentEncodingHeader, gzipEncoding) + h := writer.Header() + h.Del("Content-Length") // avoid stale length after compression + h.Set(contentEncodingHeader, gzipEncoding) return &compressedResponseWriter{ ResponseWriter: writer, writer: gzip.NewWriter(writer), } case deflateEncoding: - writer.Header().Set(contentEncodingHeader, deflateEncoding) + h := writer.Header() + h.Del("Content-Length") + h.Set(contentEncodingHeader, deflateEncoding) return &compressedResponseWriter{ ResponseWriter: writer, writer: zlib.NewWriter(writer),