From 592790bb4383d16b83a32cf7d419d14078fbe650 Mon Sep 17 00:00:00 2001 From: haoxin Date: Sun, 24 Apr 2016 21:07:55 +0800 Subject: [PATCH] middleware: add method override --- middleware/method_override.go | 39 +++++++++++++++++++++++++++ middleware/method_override_test.go | 43 ++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 middleware/method_override.go create mode 100644 middleware/method_override_test.go diff --git a/middleware/method_override.go b/middleware/method_override.go new file mode 100644 index 00000000..94379614 --- /dev/null +++ b/middleware/method_override.go @@ -0,0 +1,39 @@ +package middleware + +import ( + "github.com/labstack/echo" +) + +const ( + HttpMethodOverrideHeader = "X-HTTP-Method-Override" +) + +func OverrideMethod() echo.MiddlewareFunc { + return Override() +} + +// Override checks for the X-HTTP-Method-Override header +// or the body for parameter, `_method` +// and uses the http method instead of Request.Method. +// It isn't secure to override e.g a GET to a POST, +// so only Request.Method which are POSTs are considered. +func Override() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + originalMethod := c.Request().Method() + + if originalMethod == "POST" { + m := c.FormValue("_method") + if m != "" { + c.Request().SetMethod(m) + } + m = c.Request().Header().Get(HttpMethodOverrideHeader) + if m != "" { + c.Request().SetMethod(m) + } + } + + return next(c) + } + } +} diff --git a/middleware/method_override_test.go b/middleware/method_override_test.go new file mode 100644 index 00000000..28c00762 --- /dev/null +++ b/middleware/method_override_test.go @@ -0,0 +1,43 @@ +package middleware + +import ( + "bytes" + "net/http" + "testing" + + "github.com/labstack/echo" + "github.com/labstack/echo/test" + "github.com/stretchr/testify/assert" +) + +func TestOverrideMtrhod(t *testing.T) { + e := echo.New() + methodOverride := OverrideMethod() + h := methodOverride(func(c echo.Context) error { + return c.String(http.StatusOK, c.Request().Method()) + }) + + // Override with http header + rq := test.NewRequest(echo.POST, "/", nil) + rq.Header().Set(HttpMethodOverrideHeader, "DELETE") + rc := test.NewResponseRecorder() + c := e.NewContext(rq, rc) + h(c) + assert.Equal(t, "DELETE", rc.Body.String()) + + // Override with body parameter + rq = test.NewRequest(echo.POST, "/", bytes.NewReader([]byte("_method=DELETE"))) + rq.Header().Set(echo.HeaderContentType, echo.MIMEApplicationForm) + rc = test.NewResponseRecorder() + c = e.NewContext(rq, rc) + h(c) + assert.Equal(t, "DELETE", rc.Body.String()) + + // Ignore GET + rq = test.NewRequest(echo.GET, "/", nil) + rq.Header().Set(HttpMethodOverrideHeader, "DELETE") + rc = test.NewResponseRecorder() + c = e.NewContext(rq, rc) + h(c) + assert.Equal(t, "GET", rc.Body.String()) +}