From c6d2a9711e26b823c6072905e1051e5e2e28fb61 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 24 Jul 2018 23:40:26 +0200 Subject: [PATCH 1/5] Added feature to map url params to a struct with the default binder --- bind.go | 13 +++++++++++++ bind_test.go | 30 ++++++++++++++++++++++++++++++ echo_test.go | 4 ++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/bind.go b/bind.go index 4c372481b..7675614b9 100644 --- a/bind.go +++ b/bind.go @@ -30,6 +30,19 @@ 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() + paramVars := make(map[string][]string) + for in, name := range paramNames { + // Fix for an echo bug where a param name would show up which dont exist if its name contains "id" e.g. "userid" + names := strings.Split(name, ",") + for _, n := range names { + paramVars[n] = append(paramVars[name], paramValues[in]) + } + } + b.bindData(i, paramVars, "param") + if req.ContentLength == 0 { if req.Method == GET || req.Method == DELETE { if err = b.bindData(i, c.QueryParams(), "query"); err != nil { diff --git a/bind_test.go b/bind_test.go index dd78b759a..3789a21ed 100644 --- a/bind_test.go +++ b/bind_test.go @@ -234,6 +234,36 @@ func TestBindbindData(t *testing.T) { assertBindTestStruct(t, 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) + } +} + func TestBindUnmarshalTypeError(t *testing.T) { body := bytes.NewBufferString(`{ "id": "text" }`) e := New() diff --git a/echo_test.go b/echo_test.go index 17c64f851..2a6866625 100644 --- a/echo_test.go +++ b/echo_test.go @@ -16,8 +16,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"` } ) From f19eacde030a98545b6ea7c051debe670373a814 Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 25 Jul 2018 16:04:19 +0200 Subject: [PATCH 2/5] Added test for mix of POST data and bound params --- bind_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bind_test.go b/bind_test.go index 3789a21ed..fd847db46 100644 --- a/bind_test.go +++ b/bind_test.go @@ -262,6 +262,26 @@ func TestBindParam(t *testing.T) { 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) { From a4da9db555fda8404e76c66b05f54e9d4c472561 Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 25 Jul 2018 21:48:39 +0200 Subject: [PATCH 3/5] Renamed variables --- bind.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bind.go b/bind.go index 7675614b9..380b9362d 100644 --- a/bind.go +++ b/bind.go @@ -33,15 +33,15 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) { paramNames := c.ParamNames() paramValues := c.ParamValues() - paramVars := make(map[string][]string) - for in, name := range paramNames { + params := make(map[string][]string) + for i, name := range paramNames { // Fix for an echo bug where a param name would show up which dont exist if its name contains "id" e.g. "userid" names := strings.Split(name, ",") for _, n := range names { - paramVars[n] = append(paramVars[name], paramValues[in]) + params[n] = append(params[name], paramValues[i]) } } - b.bindData(i, paramVars, "param") + b.bindData(i, params, "param") if req.ContentLength == 0 { if req.Method == GET || req.Method == DELETE { From 524a3f2c189bed637b5cfdbac619680df55e598f Mon Sep 17 00:00:00 2001 From: konrad Date: Fri, 30 Nov 2018 16:32:23 +0100 Subject: [PATCH 4/5] Added error check --- bind.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bind.go b/bind.go index 70e9b92c4..3ae7428ab 100644 --- a/bind.go +++ b/bind.go @@ -41,7 +41,9 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) { params[n] = append(params[name], paramValues[i]) } } - b.bindData(i, params, "param") + 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 { From 3b0700f6d073b7696c7e54bb419dd34cc769daa5 Mon Sep 17 00:00:00 2001 From: kolaente Date: Fri, 21 Jun 2019 13:30:36 +0200 Subject: [PATCH 5/5] Removed unneded fix --- bind.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bind.go b/bind.go index 0578b3af0..a3f04234f 100644 --- a/bind.go +++ b/bind.go @@ -38,11 +38,7 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) { paramValues := c.ParamValues() params := make(map[string][]string) for i, name := range paramNames { - // Fix for an echo bug where a param name would show up which dont exist if its name contains "id" e.g. "userid" - names := strings.Split(name, ",") - for _, n := range names { - params[n] = append(params[name], paramValues[i]) - } + params[name] = []string{paramValues[i]} } if err := b.bindData(i, params, "param"); err != nil { return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)