diff --git a/pkg/echox/query_binder.go b/pkg/echox/query_binder.go new file mode 100644 index 0000000..6c2344f --- /dev/null +++ b/pkg/echox/query_binder.go @@ -0,0 +1,25 @@ +package echox + +import "github.com/labstack/echo/v4" + +// UseDefaultQueryBinder change behavior of query binder to use default binder +// enable always bind query params +// cause https://github.com/labstack/echo/issues/1670 disable bind query params for POST/PUT methods +func UseDefaultQueryBinder(e *echo.Echo) { + e.Binder = &defaultQueryBinder{ + binder: e.Binder, + defaultBinder: new(echo.DefaultBinder), + } +} + +type defaultQueryBinder struct { + binder echo.Binder + defaultBinder *echo.DefaultBinder +} + +func (b *defaultQueryBinder) Bind(i interface{}, c echo.Context) error { + if err := b.defaultBinder.BindQueryParams(c, i); err != nil { + return err + } + return b.binder.Bind(i, c) +} diff --git a/pkg/echox/query_binder_test.go b/pkg/echox/query_binder_test.go new file mode 100644 index 0000000..6bb7a69 --- /dev/null +++ b/pkg/echox/query_binder_test.go @@ -0,0 +1,51 @@ +package echox + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/labstack/echo/v4" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_query_binder_query_param(t *testing.T) { + type Foo struct { + Id int `json:"id"` + Name string `json:"name" query:"name"` + } + + build := func() (*echo.Echo, *httptest.ResponseRecorder, echo.Context) { + e := echo.New() + req := httptest.NewRequest(http.MethodPost, "/api/endpoint?name=foo", strings.NewReader(`{"id": 1}`)) + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + return e, rec, c + } + + handler := func(c echo.Context) error { + var foo Foo + if err := c.Bind(&foo); err != nil { + return err + } + return c.JSON(http.StatusOK, foo) + } + + e, rec, c := build() + err := handler(c) + require.NoError(t, err) + body := rec.Body.String() + assert.Contains(t, body, `"id":1`) + assert.Contains(t, body, `"name":""`) + + e, rec, c = build() + UseDefaultQueryBinder(e) + err = handler(c) + require.NoError(t, err) + body = rec.Body.String() + assert.Contains(t, body, `"id":1`) + assert.Contains(t, body, `"name":"foo"`) +}