From 858270f6f5e4fd02d9e147e8a6b0d97df023f14b Mon Sep 17 00:00:00 2001 From: kolaente Date: Fri, 21 Jun 2019 15:12:55 +0200 Subject: [PATCH] Added feature to map url params to a struct with the default binder (#1165) * Added feature to map url params to a struct with the default binder * Added test for mix of POST data and bound params * Renamed variables * Added error check * Removed unneded fix --- bind.go | 11 +++++++++++ bind_test.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ echo_test.go | 4 ++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/bind.go b/bind.go index 07d8034c..a3f04234 100644 --- a/bind.go +++ b/bind.go @@ -33,6 +33,17 @@ type ( // Bind implements the `Binder#Bind` function. func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) { req := c.Request() + + paramNames := c.ParamNames() + paramValues := c.ParamValues() + params := make(map[string][]string) + for i, name := range paramNames { + params[name] = []string{paramValues[i]} + } + if err := b.bindData(i, params, "param"); err != nil { + return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err) + } + if req.ContentLength == 0 { if req.Method == http.MethodGet || req.Method == http.MethodDelete { if err = b.bindData(i, c.QueryParams(), "query"); err != nil { diff --git a/bind_test.go b/bind_test.go index 0adb8003..0301a374 100644 --- a/bind_test.go +++ b/bind_test.go @@ -294,6 +294,56 @@ func TestBindbindData(t *testing.T) { assertBindTestStruct(assert, ts) } +func TestBindParam(t *testing.T) { + e := New() + req := httptest.NewRequest(GET, "/", nil) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + c.SetPath("/users/:id/:name") + c.SetParamNames("id", "name") + c.SetParamValues("1", "Jon Snow") + + u := new(user) + err := c.Bind(u) + if assert.NoError(t, err) { + assert.Equal(t, 1, u.ID) + assert.Equal(t, "Jon Snow", u.Name) + } + + // Second test for the absence of a param + c2 := e.NewContext(req, rec) + c2.SetPath("/users/:id") + c2.SetParamNames("id") + c2.SetParamValues("1") + + u = new(user) + err = c2.Bind(u) + if assert.NoError(t, err) { + assert.Equal(t, 1, u.ID) + assert.Equal(t, "", u.Name) + } + + // Bind something with param and post data payload + body := bytes.NewBufferString(`{ "name": "Jon Snow" }`) + e2 := New() + req2 := httptest.NewRequest(POST, "/", body) + req2.Header.Set(HeaderContentType, MIMEApplicationJSON) + + rec2 := httptest.NewRecorder() + + c3 := e2.NewContext(req2, rec2) + c3.SetPath("/users/:id") + c3.SetParamNames("id") + c3.SetParamValues("1") + + u = new(user) + err = c3.Bind(u) + if assert.NoError(t, err) { + assert.Equal(t, 1, u.ID) + assert.Equal(t, "Jon Snow", u.Name) + } +} + func TestBindUnmarshalTypeError(t *testing.T) { body := bytes.NewBufferString(`{ "id": "text" }`) e := New() diff --git a/echo_test.go b/echo_test.go index dec713ec..4eb42818 100644 --- a/echo_test.go +++ b/echo_test.go @@ -18,8 +18,8 @@ import ( type ( user struct { - ID int `json:"id" xml:"id" form:"id" query:"id"` - Name string `json:"name" xml:"name" form:"name" query:"name"` + ID int `json:"id" xml:"id" form:"id" query:"id" param:"id"` + Name string `json:"name" xml:"name" form:"name" query:"name" param:"name"` } )