From f26e572d298f0fd7186a84764e3832b6d70f5edf Mon Sep 17 00:00:00 2001 From: sonnemusk Date: Wed, 22 Jul 2026 13:47:57 +0800 Subject: [PATCH 1/2] fix(middleware): normalize MethodOverride method to uppercase Overridden methods such as "delete" did not match router http.Method* constants. Trim and uppercase the override value before assigning. --- middleware/method_override.go | 6 ++++-- middleware/method_override_test.go | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/middleware/method_override.go b/middleware/method_override.go index 25ec1f935..40306997c 100644 --- a/middleware/method_override.go +++ b/middleware/method_override.go @@ -5,6 +5,7 @@ package middleware import ( "net/http" + "strings" "github.com/labstack/echo/v5" ) @@ -60,9 +61,10 @@ func (config MethodOverrideConfig) ToMiddleware() (echo.MiddlewareFunc, error) { req := c.Request() if req.Method == http.MethodPost { - m := config.Getter(c) + m := strings.TrimSpace(config.Getter(c)) if m != "" { - req.Method = m + // Normalize to uppercase so routing matches http.Method* constants. + req.Method = strings.ToUpper(m) } } return next(c) diff --git a/middleware/method_override_test.go b/middleware/method_override_test.go index 525ad10ba..3bded91fe 100644 --- a/middleware/method_override_test.go +++ b/middleware/method_override_test.go @@ -90,3 +90,19 @@ func TestMethodOverride_ignoreGet(t *testing.T) { assert.Equal(t, http.MethodGet, req.Method) } + +func TestMethodOverride_normalizeCase(t *testing.T) { + e := echo.New() + m := MethodOverride() + h := m(func(c *echo.Context) error { + return c.String(http.StatusOK, c.Request().Method) + }) + + req := httptest.NewRequest(http.MethodPost, "/", nil) + req.Header.Set(echo.HeaderXHTTPMethodOverride, "delete") + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + assert.NoError(t, h(c)) + assert.Equal(t, http.MethodDelete, req.Method) + assert.Equal(t, http.MethodDelete, rec.Body.String()) +} From a4dd59191141c4b363574a766750ef1fcf3c9f4e Mon Sep 17 00:00:00 2001 From: sonnemusk Date: Wed, 22 Jul 2026 15:28:51 +0800 Subject: [PATCH 2/2] docs(middleware): clarify MethodOverrideGetter return value Per review: do not normalize override methods in middleware. Document that Getter should return a standard method name (e.g. http.MethodDelete). --- middleware/method_override.go | 11 ++++++----- middleware/method_override_test.go | 16 ---------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/middleware/method_override.go b/middleware/method_override.go index 40306997c..17335a902 100644 --- a/middleware/method_override.go +++ b/middleware/method_override.go @@ -5,7 +5,6 @@ package middleware import ( "net/http" - "strings" "github.com/labstack/echo/v5" ) @@ -20,7 +19,10 @@ type MethodOverrideConfig struct { Getter MethodOverrideGetter } -// MethodOverrideGetter is a function that gets overridden method from the request +// MethodOverrideGetter is a function that gets overridden method from the request. +// The returned value should be a standard HTTP method name as used by net/http +// (e.g. http.MethodDelete, "DELETE"). The middleware does not normalize case or +// trim spaces — callers / Getter implementations should return a valid method. type MethodOverrideGetter func(c *echo.Context) string // DefaultMethodOverrideConfig is the default MethodOverride middleware config. @@ -61,10 +63,9 @@ func (config MethodOverrideConfig) ToMiddleware() (echo.MiddlewareFunc, error) { req := c.Request() if req.Method == http.MethodPost { - m := strings.TrimSpace(config.Getter(c)) + m := config.Getter(c) if m != "" { - // Normalize to uppercase so routing matches http.Method* constants. - req.Method = strings.ToUpper(m) + req.Method = m } } return next(c) diff --git a/middleware/method_override_test.go b/middleware/method_override_test.go index 3bded91fe..525ad10ba 100644 --- a/middleware/method_override_test.go +++ b/middleware/method_override_test.go @@ -90,19 +90,3 @@ func TestMethodOverride_ignoreGet(t *testing.T) { assert.Equal(t, http.MethodGet, req.Method) } - -func TestMethodOverride_normalizeCase(t *testing.T) { - e := echo.New() - m := MethodOverride() - h := m(func(c *echo.Context) error { - return c.String(http.StatusOK, c.Request().Method) - }) - - req := httptest.NewRequest(http.MethodPost, "/", nil) - req.Header.Set(echo.HeaderXHTTPMethodOverride, "delete") - rec := httptest.NewRecorder() - c := e.NewContext(req, rec) - assert.NoError(t, h(c)) - assert.Equal(t, http.MethodDelete, req.Method) - assert.Equal(t, http.MethodDelete, rec.Body.String()) -}