From dac7cacd4df35e96a4d8c7d09b925bb432509884 Mon Sep 17 00:00:00 2001 From: darkweak Date: Tue, 20 Dec 2022 21:26:53 +0100 Subject: encode: Respect Cache-Control no-transform (#5257) * encode: respect Cache-Control HTTP header no-transform * encode: switch to strings.Contains --- modules/caddyhttp/encode/encode.go | 20 +++++++++----- modules/caddyhttp/encode/encode_test.go | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/modules/caddyhttp/encode/encode.go b/modules/caddyhttp/encode/encode.go index 91e7060..e3a6267 100644 --- a/modules/caddyhttp/encode/encode.go +++ b/modules/caddyhttp/encode/encode.go @@ -117,14 +117,20 @@ func (enc *Encode) Validate() error { return nil } +func isEncodeAllowed(h http.Header) bool { + return !strings.Contains(h.Get("Cache-Control"), "no-transform") +} + func (enc *Encode) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { - for _, encName := range AcceptedEncodings(r, enc.Prefer) { - if _, ok := enc.writerPools[encName]; !ok { - continue // encoding not offered + if isEncodeAllowed(r.Header) { + for _, encName := range AcceptedEncodings(r, enc.Prefer) { + if _, ok := enc.writerPools[encName]; !ok { + continue // encoding not offered + } + w = enc.openResponseWriter(encName, w) + defer w.(*responseWriter).Close() + break } - w = enc.openResponseWriter(encName, w) - defer w.(*responseWriter).Close() - break } return next.ServeHTTP(w, r) } @@ -281,7 +287,7 @@ func (rw *responseWriter) Close() error { // init should be called before we write a response, if rw.buf has contents. func (rw *responseWriter) init() { - if rw.Header().Get("Content-Encoding") == "" && + if rw.Header().Get("Content-Encoding") == "" && isEncodeAllowed(rw.Header()) && rw.config.Match(rw) { rw.w = rw.config.writerPools[rw.encodingName].Get().(Encoder) diff --git a/modules/caddyhttp/encode/encode_test.go b/modules/caddyhttp/encode/encode_test.go index 5f1e3f2..3374ee3 100644 --- a/modules/caddyhttp/encode/encode_test.go +++ b/modules/caddyhttp/encode/encode_test.go @@ -261,3 +261,50 @@ func TestValidate(t *testing.T) { } } + +func TestIsEncodeAllowed(t *testing.T) { + testCases := []struct { + name string + headers http.Header + expected bool + }{ + { + name: "Without any headers", + headers: http.Header{}, + expected: true, + }, + { + name: "Without Cache-Control HTTP header", + headers: http.Header{ + "Accept-Encoding": {"gzip"}, + }, + expected: true, + }, + { + name: "Cache-Control HTTP header ending with no-transform directive", + headers: http.Header{ + "Accept-Encoding": {"gzip"}, + "Cache-Control": {"no-cache; no-transform"}, + }, + expected: false, + }, + { + name: "With Cache-Control HTTP header no-transform as Cache-Extension value", + headers: http.Header{ + "Accept-Encoding": {"gzip"}, + "Cache-Control": {`no-store; no-cache; community="no-transform"`}, + }, + expected: false, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + if result := isEncodeAllowed(test.headers); result != test.expected { + t.Errorf("The headers given to the isEncodeAllowed should return %t, %t given.", + result, + test.expected) + } + }) + } +} -- cgit v1.2.3