diff --git a/docs/content/middlewares/http/compress.md b/docs/content/middlewares/http/compress.md index e98954660..d3f2e1085 100644 --- a/docs/content/middlewares/http/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -214,3 +214,44 @@ http: [http.middlewares.test-compress.compress] minResponseBodyBytes = 1200 ``` + +### `defaultEncoding` + +_Optional, Default=""_ + +`defaultEncoding` specifies the default encoding if the `Accept-Encoding` header is not in the request or contains a wildcard (`*`). + +There is no fallback on the `defaultEncoding` when the header value is empty or unsupported. + +```yaml tab="Docker & Swarm" +labels: + - "traefik.http.middlewares.test-compress.compress.defaultEncoding=gzip" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-compress +spec: + compress: + defaultEncoding: gzip +``` + +```yaml tab="Consul Catalog" +- "traefik.http.middlewares.test-compress.compress.defaultEncoding=gzip" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-compress: + compress: + defaultEncoding: gzip +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-compress.compress] + defaultEncoding = "gzip" +``` diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index 5c21cab3d..319988894 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -18,6 +18,7 @@ - "traefik.http.middlewares.middleware05.circuitbreaker.recoveryduration=42s" - "traefik.http.middlewares.middleware05.circuitbreaker.responsecode=42" - "traefik.http.middlewares.middleware06.compress=true" +- "traefik.http.middlewares.middleware06.compress.defaultencoding=foobar" - "traefik.http.middlewares.middleware06.compress.excludedcontenttypes=foobar, foobar" - "traefik.http.middlewares.middleware06.compress.includedcontenttypes=foobar, foobar" - "traefik.http.middlewares.middleware06.compress.minresponsebodybytes=42" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index d3cf0eaf2..a42f9ba17 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -143,6 +143,7 @@ excludedContentTypes = ["foobar", "foobar"] includedContentTypes = ["foobar", "foobar"] minResponseBodyBytes = 42 + defaultEncoding = "foobar" [http.middlewares.Middleware07] [http.middlewares.Middleware07.contentType] autoDetect = true diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index fdba1c332..6f675e626 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -152,6 +152,7 @@ http: - foobar - foobar minResponseBodyBytes: 42 + defaultEncoding: foobar Middleware07: contentType: autoDetect: true diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index a7bd8b184..0e42074f9 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -825,6 +825,11 @@ spec: This middleware compresses responses before sending them to the client, using gzip compression. More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/compress/ properties: + defaultEncoding: + description: DefaultEncoding specifies the default encoding if + the `Accept-Encoding` header is not in the request or contains + a wildcard (`*`). + type: string excludedContentTypes: description: |- ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing. diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index 254801508..cd425b710 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -21,6 +21,7 @@ THIS FILE MUST NOT BE EDITED BY HAND | `traefik/http/middlewares/Middleware05/circuitBreaker/fallbackDuration` | `42s` | | `traefik/http/middlewares/Middleware05/circuitBreaker/recoveryDuration` | `42s` | | `traefik/http/middlewares/Middleware05/circuitBreaker/responseCode` | `42` | +| `traefik/http/middlewares/Middleware06/compress/defaultEncoding` | `foobar` | | `traefik/http/middlewares/Middleware06/compress/excludedContentTypes/0` | `foobar` | | `traefik/http/middlewares/Middleware06/compress/excludedContentTypes/1` | `foobar` | | `traefik/http/middlewares/Middleware06/compress/includedContentTypes/0` | `foobar` | diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml index 281e70369..a096d770d 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml @@ -183,6 +183,11 @@ spec: This middleware compresses responses before sending them to the client, using gzip compression. More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/compress/ properties: + defaultEncoding: + description: DefaultEncoding specifies the default encoding if + the `Accept-Encoding` header is not in the request or contains + a wildcard (`*`). + type: string excludedContentTypes: description: |- ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing. diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index a7bd8b184..0e42074f9 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -825,6 +825,11 @@ spec: This middleware compresses responses before sending them to the client, using gzip compression. More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/compress/ properties: + defaultEncoding: + description: DefaultEncoding specifies the default encoding if + the `Accept-Encoding` header is not in the request or contains + a wildcard (`*`). + type: string excludedContentTypes: description: |- ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing. diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index 59c91814b..0a6f63ba0 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -174,6 +174,8 @@ type Compress struct { // MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed. // Default: 1024. MinResponseBodyBytes int `json:"minResponseBodyBytes,omitempty" toml:"minResponseBodyBytes,omitempty" yaml:"minResponseBodyBytes,omitempty" export:"true"` + // DefaultEncoding specifies the default encoding if the `Accept-Encoding` header is not in the request or contains a wildcard (`*`). + DefaultEncoding string `json:"defaultEncoding,omitempty" toml:"defaultEncoding,omitempty" yaml:"defaultEncoding,omitempty" export:"true"` } // +k8s:deepcopy-gen=true diff --git a/pkg/middlewares/compress/acceptencoding.go b/pkg/middlewares/compress/acceptencoding.go new file mode 100644 index 000000000..084a8f263 --- /dev/null +++ b/pkg/middlewares/compress/acceptencoding.go @@ -0,0 +1,137 @@ +package compress + +import ( + "slices" + "strconv" + "strings" +) + +const acceptEncodingHeader = "Accept-Encoding" + +const ( + brotliName = "br" + gzipName = "gzip" + identityName = "identity" + wildcardName = "*" + notAcceptable = "not_acceptable" +) + +type Encoding struct { + Type string + Weight *float64 +} + +func getCompressionType(acceptEncoding []string, defaultType string) string { + if defaultType == "" { + // Keeps the pre-existing default inside Traefik. + defaultType = brotliName + } + + encodings, hasWeight := parseAcceptEncoding(acceptEncoding) + + if hasWeight { + if len(encodings) == 0 { + return identityName + } + + encoding := encodings[0] + + if encoding.Type == identityName && encoding.Weight != nil && *encoding.Weight == 0 { + return notAcceptable + } + + if encoding.Type == wildcardName && encoding.Weight != nil && *encoding.Weight == 0 { + return notAcceptable + } + + if encoding.Type == wildcardName { + return defaultType + } + + return encoding.Type + } + + for _, dt := range []string{brotliName, gzipName} { + if slices.ContainsFunc(encodings, func(e Encoding) bool { return e.Type == dt }) { + return dt + } + } + + if slices.ContainsFunc(encodings, func(e Encoding) bool { return e.Type == wildcardName }) { + return defaultType + } + + return identityName +} + +func parseAcceptEncoding(acceptEncoding []string) ([]Encoding, bool) { + var encodings []Encoding + var hasWeight bool + + for _, line := range acceptEncoding { + for _, item := range strings.Split(strings.ReplaceAll(line, " ", ""), ",") { + parsed := strings.SplitN(item, ";", 2) + if len(parsed) == 0 { + continue + } + + switch parsed[0] { + case brotliName, gzipName, identityName, wildcardName: + // supported encoding + default: + continue + } + + var weight *float64 + if len(parsed) > 1 && strings.HasPrefix(parsed[1], "q=") { + w, _ := strconv.ParseFloat(strings.TrimPrefix(parsed[1], "q="), 64) + + weight = &w + hasWeight = true + } + + encodings = append(encodings, Encoding{ + Type: parsed[0], + Weight: weight, + }) + } + } + + slices.SortFunc(encodings, compareEncoding) + + return encodings, hasWeight +} + +func compareEncoding(a, b Encoding) int { + lhs, rhs := a.Weight, b.Weight + + if lhs == nil && rhs == nil { + return 0 + } + + if lhs == nil && *rhs == 0 { + return -1 + } + + if lhs == nil { + return 1 + } + + if rhs == nil && *lhs == 0 { + return 1 + } + + if rhs == nil { + return -1 + } + + if *lhs < *rhs { + return 1 + } + + if *lhs > *rhs { + return -1 + } + + return 0 +} diff --git a/pkg/middlewares/compress/acceptencoding_test.go b/pkg/middlewares/compress/acceptencoding_test.go new file mode 100644 index 000000000..858e6795e --- /dev/null +++ b/pkg/middlewares/compress/acceptencoding_test.go @@ -0,0 +1,143 @@ +package compress + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_getCompressionType(t *testing.T) { + testCases := []struct { + desc string + values []string + defaultType string + expected string + }{ + { + desc: "br > gzip (no weight)", + values: []string{"gzip, br"}, + expected: brotliName, + }, + { + desc: "known compression type (no weight)", + values: []string{"compress, gzip"}, + expected: gzipName, + }, + { + desc: "unknown compression type (no weight), no encoding", + values: []string{"compress, rar"}, + expected: identityName, + }, + { + desc: "wildcard return the default compression type", + values: []string{"*"}, + expected: brotliName, + }, + { + desc: "wildcard return the custom default compression type", + values: []string{"*"}, + defaultType: "foo", + expected: "foo", + }, + { + desc: "follows weight", + values: []string{"br;q=0.8, gzip;q=1.0, *;q=0.1"}, + expected: gzipName, + }, + { + desc: "ignore unknown compression type", + values: []string{"compress;q=1.0, gzip;q=0.5"}, + expected: gzipName, + }, + { + desc: "not acceptable (identity)", + values: []string{"compress;q=1.0, identity;q=0"}, + expected: notAcceptable, + }, + { + desc: "not acceptable (wildcard)", + values: []string{"compress;q=1.0, *;q=0"}, + expected: notAcceptable, + }, + { + desc: "non-zero is higher than 0", + values: []string{"gzip, *;q=0"}, + expected: gzipName, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + encodingType := getCompressionType(test.values, test.defaultType) + + assert.Equal(t, test.expected, encodingType) + }) + } +} + +func Test_parseAcceptEncoding(t *testing.T) { + testCases := []struct { + desc string + values []string + expected []Encoding + assertWeight assert.BoolAssertionFunc + }{ + { + desc: "weight", + values: []string{"br;q=1.0, gzip;q=0.8, *;q=0.1"}, + expected: []Encoding{ + {Type: brotliName, Weight: ptr[float64](1)}, + {Type: gzipName, Weight: ptr(0.8)}, + {Type: wildcardName, Weight: ptr(0.1)}, + }, + assertWeight: assert.True, + }, + { + desc: "mixed", + values: []string{"gzip, br;q=1.0, *;q=0"}, + expected: []Encoding{ + {Type: brotliName, Weight: ptr[float64](1)}, + {Type: gzipName}, + {Type: wildcardName, Weight: ptr[float64](0)}, + }, + assertWeight: assert.True, + }, + { + desc: "no weight", + values: []string{"gzip, br, *"}, + expected: []Encoding{ + {Type: gzipName}, + {Type: brotliName}, + {Type: wildcardName}, + }, + assertWeight: assert.False, + }, + { + desc: "weight and identity", + values: []string{"gzip;q=1.0, identity; q=0.5, *;q=0"}, + expected: []Encoding{ + {Type: gzipName, Weight: ptr[float64](1)}, + {Type: identityName, Weight: ptr(0.5)}, + {Type: wildcardName, Weight: ptr[float64](0)}, + }, + assertWeight: assert.True, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + aes, hasWeight := parseAcceptEncoding(test.values) + + assert.Equal(t, test.expected, aes) + test.assertWeight(t, hasWeight) + }) + } +} + +func ptr[T any](t T) *T { + return &t +} diff --git a/pkg/middlewares/compress/compress.go b/pkg/middlewares/compress/compress.go index bde909978..514fddb2e 100644 --- a/pkg/middlewares/compress/compress.go +++ b/pkg/middlewares/compress/compress.go @@ -7,7 +7,6 @@ import ( "mime" "net/http" "slices" - "strings" "github.com/klauspost/compress/gzhttp" "github.com/traefik/traefik/v3/pkg/config/dynamic" @@ -24,11 +23,12 @@ const DefaultMinSize = 1024 // Compress is a middleware that allows to compress the response. type compress struct { - next http.Handler - name string - excludes []string - includes []string - minSize int + next http.Handler + name string + excludes []string + includes []string + minSize int + defaultEncoding string brotliHandler http.Handler gzipHandler http.Handler @@ -68,11 +68,12 @@ func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name str } c := &compress{ - next: next, - name: name, - excludes: excludes, - includes: includes, - minSize: minSize, + next: next, + name: name, + excludes: excludes, + includes: includes, + minSize: minSize, + defaultEncoding: conf.DefaultEncoding, } var err error @@ -109,25 +110,33 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return } - // Client doesn't specify a preferred encoding, for compatibility don't encode the request - // See https://github.com/traefik/traefik/issues/9734 - acceptEncoding, ok := req.Header["Accept-Encoding"] + acceptEncoding, ok := req.Header[acceptEncodingHeader] if !ok { + if c.defaultEncoding != "" { + // RFC says: "If no Accept-Encoding header field is in the request, any content coding is considered acceptable by the user agent." + // https://www.rfc-editor.org/rfc/rfc9110#field.accept-encoding + c.chooseHandler(c.defaultEncoding, rw, req) + return + } + + // Client doesn't specify a preferred encoding, for compatibility don't encode the request + // See https://github.com/traefik/traefik/issues/9734 c.next.ServeHTTP(rw, req) return } - if encodingAccepts(acceptEncoding, "br") { + c.chooseHandler(getCompressionType(acceptEncoding, c.defaultEncoding), rw, req) +} + +func (c *compress) chooseHandler(typ string, rw http.ResponseWriter, req *http.Request) { + switch typ { + case brotliName: c.brotliHandler.ServeHTTP(rw, req) - return - } - - if encodingAccepts(acceptEncoding, "gzip") { + case gzipName: c.gzipHandler.ServeHTTP(rw, req) - return + default: + c.next.ServeHTTP(rw, req) } - - c.next.ServeHTTP(rw, req) } func (c *compress) GetTracingInformation() (string, string, trace.SpanKind) { @@ -172,19 +181,3 @@ func (c *compress) newBrotliHandler() (http.Handler, error) { return wrapper(c.next), nil } - -func encodingAccepts(acceptEncoding []string, typ string) bool { - for _, ae := range acceptEncoding { - for _, e := range strings.Split(ae, ",") { - parsed := strings.Split(strings.TrimSpace(e), ";") - if len(parsed) == 0 { - continue - } - if parsed[0] == typ || parsed[0] == "*" { - return true - } - } - } - - return false -} diff --git a/pkg/middlewares/compress/compress_test.go b/pkg/middlewares/compress/compress_test.go index 1ea6afb45..556d9f5fa 100644 --- a/pkg/middlewares/compress/compress_test.go +++ b/pkg/middlewares/compress/compress_test.go @@ -18,12 +18,9 @@ import ( ) const ( - acceptEncodingHeader = "Accept-Encoding" contentEncodingHeader = "Content-Encoding" contentTypeHeader = "Content-Type" varyHeader = "Vary" - gzipValue = "gzip" - brotliValue = "br" ) func TestNegotiation(t *testing.T) { @@ -62,9 +59,9 @@ func TestNegotiation(t *testing.T) { expEncoding: "br", }, { - desc: "multi accept header, prefer br", + desc: "multi accept header, prefer gzip", acceptEncHeader: "gzip;q=1.0, br;q=0.8", - expEncoding: "br", + expEncoding: "gzip", }, { desc: "multi accept header list, prefer br", @@ -98,7 +95,7 @@ func TestNegotiation(t *testing.T) { func TestShouldCompressWhenNoContentEncodingHeader(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) baseBody := generateBytes(gzhttp.DefaultMinSize) @@ -112,7 +109,7 @@ func TestShouldCompressWhenNoContentEncodingHeader(t *testing.T) { rw := httptest.NewRecorder() handler.ServeHTTP(rw, req) - assert.Equal(t, gzipValue, rw.Header().Get(contentEncodingHeader)) + assert.Equal(t, gzipName, rw.Header().Get(contentEncodingHeader)) assert.Equal(t, acceptEncodingHeader, rw.Header().Get(varyHeader)) gr, err := gzip.NewReader(rw.Body) @@ -125,11 +122,11 @@ func TestShouldCompressWhenNoContentEncodingHeader(t *testing.T) { func TestShouldNotCompressWhenContentEncodingHeader(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) fakeCompressedBody := generateBytes(gzhttp.DefaultMinSize) next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Header().Add(contentEncodingHeader, gzipValue) + rw.Header().Add(contentEncodingHeader, gzipName) rw.Header().Add(varyHeader, acceptEncodingHeader) _, err := rw.Write(fakeCompressedBody) if err != nil { @@ -142,7 +139,7 @@ func TestShouldNotCompressWhenContentEncodingHeader(t *testing.T) { rw := httptest.NewRecorder() handler.ServeHTTP(rw, req) - assert.Equal(t, gzipValue, rw.Header().Get(contentEncodingHeader)) + assert.Equal(t, gzipName, rw.Header().Get(contentEncodingHeader)) assert.Equal(t, acceptEncodingHeader, rw.Header().Get(varyHeader)) assert.EqualValues(t, rw.Body.Bytes(), fakeCompressedBody) @@ -225,7 +222,7 @@ func TestShouldNotCompressWhenEmptyAcceptEncodingHeader(t *testing.T) { func TestShouldNotCompressHeadRequest(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodHead, "http://localhost", nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) fakeBody := generateBytes(gzhttp.DefaultMinSize) next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { @@ -301,7 +298,7 @@ func TestShouldNotCompressWhenSpecificContentType(t *testing.T) { t.Parallel() req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) if test.reqContentType != "" { req.Header.Add(contentTypeHeader, test.reqContentType) } @@ -352,7 +349,7 @@ func TestShouldCompressWhenSpecificContentType(t *testing.T) { t.Parallel() req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { rw.Header().Set(contentTypeHeader, test.respContentType) @@ -368,7 +365,7 @@ func TestShouldCompressWhenSpecificContentType(t *testing.T) { rw := httptest.NewRecorder() handler.ServeHTTP(rw, req) - assert.Equal(t, gzipValue, rw.Header().Get(contentEncodingHeader)) + assert.Equal(t, gzipName, rw.Header().Get(contentEncodingHeader)) assert.Equal(t, acceptEncodingHeader, rw.Header().Get(varyHeader)) assert.NotEqualValues(t, rw.Body.Bytes(), baseBody) }) @@ -386,7 +383,7 @@ func TestIntegrationShouldNotCompress(t *testing.T) { { name: "when content already compressed", handler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Header().Add(contentEncodingHeader, gzipValue) + rw.Header().Add(contentEncodingHeader, gzipName) rw.Header().Add(varyHeader, acceptEncodingHeader) _, err := rw.Write(fakeCompressedBody) if err != nil { @@ -398,7 +395,7 @@ func TestIntegrationShouldNotCompress(t *testing.T) { { name: "when content already compressed and status code Created", handler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Header().Add(contentEncodingHeader, gzipValue) + rw.Header().Add(contentEncodingHeader, gzipName) rw.Header().Add(varyHeader, acceptEncodingHeader) rw.WriteHeader(http.StatusCreated) _, err := rw.Write(fakeCompressedBody) @@ -419,14 +416,14 @@ func TestIntegrationShouldNotCompress(t *testing.T) { defer ts.Close() req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.Equal(t, test.expectedStatusCode, resp.StatusCode) - assert.Equal(t, gzipValue, resp.Header.Get(contentEncodingHeader)) + assert.Equal(t, gzipName, resp.Header.Get(contentEncodingHeader)) assert.Equal(t, acceptEncodingHeader, resp.Header.Get(varyHeader)) body, err := io.ReadAll(resp.Body) @@ -438,7 +435,7 @@ func TestIntegrationShouldNotCompress(t *testing.T) { func TestShouldWriteHeaderWhenFlush(t *testing.T) { next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Header().Add(contentEncodingHeader, gzipValue) + rw.Header().Add(contentEncodingHeader, gzipName) rw.Header().Add(varyHeader, acceptEncodingHeader) rw.WriteHeader(http.StatusUnauthorized) rw.(http.Flusher).Flush() @@ -454,14 +451,14 @@ func TestShouldWriteHeaderWhenFlush(t *testing.T) { defer ts.Close() req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) - assert.Equal(t, gzipValue, resp.Header.Get(contentEncodingHeader)) + assert.Equal(t, gzipName, resp.Header.Get(contentEncodingHeader)) assert.Equal(t, acceptEncodingHeader, resp.Header.Get(varyHeader)) } @@ -505,14 +502,14 @@ func TestIntegrationShouldCompress(t *testing.T) { defer ts.Close() req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.Equal(t, test.expectedStatusCode, resp.StatusCode) - assert.Equal(t, gzipValue, resp.Header.Get(contentEncodingHeader)) + assert.Equal(t, gzipName, resp.Header.Get(contentEncodingHeader)) assert.Equal(t, acceptEncodingHeader, resp.Header.Get(varyHeader)) body, err := io.ReadAll(resp.Body) @@ -547,7 +544,7 @@ func TestMinResponseBodyBytes(t *testing.T) { t.Parallel() req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { if _, err := rw.Write(fakeBody); err != nil { @@ -562,7 +559,7 @@ func TestMinResponseBodyBytes(t *testing.T) { handler.ServeHTTP(rw, req) if test.expectedCompression { - assert.Equal(t, gzipValue, rw.Header().Get(contentEncodingHeader)) + assert.Equal(t, gzipName, rw.Header().Get(contentEncodingHeader)) assert.NotEqualValues(t, rw.Body.Bytes(), fakeBody) return } @@ -636,7 +633,7 @@ func Test1xxResponses(t *testing.T) { }, } req, _ := http.NewRequestWithContext(httptrace.WithClientTrace(context.Background(), trace), http.MethodGet, server.URL, nil) - req.Header.Add(acceptEncodingHeader, gzipValue) + req.Header.Add(acceptEncodingHeader, gzipName) res, err := frontendClient.Do(req) assert.NoError(t, err) @@ -648,7 +645,7 @@ func Test1xxResponses(t *testing.T) { } checkLinkHeaders(t, []string{"; rel=preload; as=style", "; rel=preload; as=script", "; rel=preload; as=script"}, res.Header["Link"]) - assert.Equal(t, gzipValue, res.Header.Get(contentEncodingHeader)) + assert.Equal(t, gzipName, res.Header.Get(contentEncodingHeader)) body, _ := io.ReadAll(res.Body) assert.NotEqualValues(t, body, fakeBody) } @@ -730,7 +727,7 @@ func runBenchmark(b *testing.B, req *http.Request, handler http.Handler) { b.Fatalf("Expected 200 but got %d", code) } - assert.Equal(b, gzipValue, res.Header().Get(contentEncodingHeader)) + assert.Equal(b, gzipName, res.Header().Get(contentEncodingHeader)) } func generateBytes(length int) []byte {