From b2829258d5e607fa701ff189dc83060263446c60 Mon Sep 17 00:00:00 2001 From: orinnz Date: Sat, 3 Oct 2026 19:08:43 +0700 Subject: [PATCH] fix(middleware): match gzip Content-Encoding case-insensitively in v4 Decompress only acted on an exact "gzip" Content-Encoding, so a body sent with "GZIP" or "Gzip" reached the handler still compressed. Content codings are case-insensitive (RFC 9110 section 8.4.1). Backport of #3056. --- middleware/decompress.go | 4 +++- middleware/decompress_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/middleware/decompress.go b/middleware/decompress.go index 0c56176ee..7eca67953 100644 --- a/middleware/decompress.go +++ b/middleware/decompress.go @@ -7,6 +7,7 @@ import ( "compress/gzip" "io" "net/http" + "strings" "sync" "github.com/labstack/echo/v4" @@ -66,7 +67,8 @@ func DecompressWithConfig(config DecompressConfig) echo.MiddlewareFunc { return next(c) } - if c.Request().Header.Get(echo.HeaderContentEncoding) != GZIPEncoding { + // content codings are case-insensitive (RFC 9110 section 8.4.1) + if !strings.EqualFold(c.Request().Header.Get(echo.HeaderContentEncoding), GZIPEncoding) { return next(c) } diff --git a/middleware/decompress_test.go b/middleware/decompress_test.go index 63b1a68f5..bc0171b8d 100644 --- a/middleware/decompress_test.go +++ b/middleware/decompress_test.go @@ -208,3 +208,29 @@ func gzipString(body string) ([]byte, error) { return buf.Bytes(), nil } + +func TestDecompressContentEncodingCaseInsensitive(t *testing.T) { + e := echo.New() + body := `{"name":"echo"}` + gz, err := gzipString(body) + assert.NoError(t, err) + + for _, encoding := range []string{"GZIP", "Gzip"} { + t.Run(encoding, func(t *testing.T) { + req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(gz)) + req.Header.Set(echo.HeaderContentEncoding, encoding) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + + h := Decompress()(func(c echo.Context) error { + b, err := io.ReadAll(c.Request().Body) + if err != nil { + return err + } + return c.String(http.StatusOK, string(b)) + }) + assert.NoError(t, h(c)) + assert.Equal(t, body, rec.Body.String()) + }) + } +}