From 3c61d32490eb09e17e229559c73d2ab048cd0a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Gim=C3=A9nez=20G=C3=A1mez?= <864706+jgimenez@users.noreply.github.com> Date: Wed, 5 Apr 2023 10:19:59 +0200 Subject: [PATCH] Allow access to internal ResponseWriter in gzhttp handler (#799) Sometimes users will want to use the `http.Flusher`, or `http.Hijacker`, etc. interfaces from an `http.ResponseWriter`, which `gzhttp.ResponseWriter` does not implement but the underlying one does. It is common to provide an `Unwrap` function to access it, for example the standard library expects that (although I didn't find any official documentation on it). See [http.ResponseController](https://cs.opensource.google/go/go/+/refs/tags/go1.20.2:src/net/http/responsecontroller.go;l=41-43) for example. --- gzhttp/compress.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gzhttp/compress.go b/gzhttp/compress.go index 6ca11b1c10..a7950b39ad 100644 --- a/gzhttp/compress.go +++ b/gzhttp/compress.go @@ -169,6 +169,10 @@ func (w *GzipResponseWriter) Write(b []byte) (int, error) { return len(b), nil } +func (w *GzipResponseWriter) Unwrap() http.ResponseWriter { + return w.ResponseWriter +} + var castagnoliTable = crc32.MakeTable(crc32.Castagnoli) // startGzip initializes a GZIP writer and writes the buffer. @@ -919,6 +923,10 @@ func atoi(s string) (int, bool) { return int(i64), err == nil } +type unwrapper interface { + Unwrap() http.ResponseWriter +} + // newNoGzipResponseWriter will return a response writer that // cleans up compression artifacts. // Depending on whether http.Hijacker is supported the returned will as well. @@ -929,10 +937,12 @@ func newNoGzipResponseWriter(w http.ResponseWriter) http.ResponseWriter { http.ResponseWriter http.Hijacker http.Flusher + unwrapper }{ ResponseWriter: n, Hijacker: hj, Flusher: n, + unwrapper: n, } return x } @@ -982,3 +992,7 @@ func (n *NoGzipResponseWriter) WriteHeader(statusCode int) { } n.ResponseWriter.WriteHeader(statusCode) } + +func (n *NoGzipResponseWriter) Unwrap() http.ResponseWriter { + return n.ResponseWriter +}