99 "mime/multipart"
1010 "net/http"
1111 "net/http/httptest"
12+ "net/url"
1213 "reflect"
1314 "strconv"
1415 "strings"
@@ -187,19 +188,26 @@ func TestToMultipleFields(t *testing.T) {
187188
188189func TestBindJSON (t * testing.T ) {
189190 assert := assert .New (t )
190- testBindOkay (assert , strings .NewReader (userJSON ), MIMEApplicationJSON )
191+ testBindOkay (assert , strings .NewReader (userJSON ), nil , MIMEApplicationJSON )
192+ testBindOkay (assert , strings .NewReader (userJSON ), dummyQuery , MIMEApplicationJSON )
193+ testBindArrayOkay (assert , strings .NewReader (usersJSON ), nil , MIMEApplicationJSON )
194+ testBindArrayOkay (assert , strings .NewReader (usersJSON ), dummyQuery , MIMEApplicationJSON )
191195 testBindError (assert , strings .NewReader (invalidContent ), MIMEApplicationJSON , & json.SyntaxError {})
192196 testBindError (assert , strings .NewReader (userJSONInvalidType ), MIMEApplicationJSON , & json.UnmarshalTypeError {})
193197}
194198
195199func TestBindXML (t * testing.T ) {
196200 assert := assert .New (t )
197201
198- testBindOkay (assert , strings .NewReader (userXML ), MIMEApplicationXML )
202+ testBindOkay (assert , strings .NewReader (userXML ), nil , MIMEApplicationXML )
203+ testBindOkay (assert , strings .NewReader (userXML ), dummyQuery , MIMEApplicationXML )
204+ testBindArrayOkay (assert , strings .NewReader (userXML ), nil , MIMEApplicationXML )
205+ testBindArrayOkay (assert , strings .NewReader (userXML ), dummyQuery , MIMEApplicationXML )
199206 testBindError (assert , strings .NewReader (invalidContent ), MIMEApplicationXML , errors .New ("" ))
200207 testBindError (assert , strings .NewReader (userXMLConvertNumberError ), MIMEApplicationXML , & strconv.NumError {})
201208 testBindError (assert , strings .NewReader (userXMLUnsupportedTypeError ), MIMEApplicationXML , & xml.SyntaxError {})
202- testBindOkay (assert , strings .NewReader (userXML ), MIMETextXML )
209+ testBindOkay (assert , strings .NewReader (userXML ), nil , MIMETextXML )
210+ testBindOkay (assert , strings .NewReader (userXML ), dummyQuery , MIMETextXML )
203211 testBindError (assert , strings .NewReader (invalidContent ), MIMETextXML , errors .New ("" ))
204212 testBindError (assert , strings .NewReader (userXMLConvertNumberError ), MIMETextXML , & strconv.NumError {})
205213 testBindError (assert , strings .NewReader (userXMLUnsupportedTypeError ), MIMETextXML , & xml.SyntaxError {})
@@ -208,7 +216,8 @@ func TestBindXML(t *testing.T) {
208216func TestBindForm (t * testing.T ) {
209217 assert := assert .New (t )
210218
211- testBindOkay (assert , strings .NewReader (userForm ), MIMEApplicationForm )
219+ testBindOkay (assert , strings .NewReader (userForm ), nil , MIMEApplicationForm )
220+ testBindOkay (assert , strings .NewReader (userForm ), dummyQuery , MIMEApplicationForm )
212221 e := New ()
213222 req := httptest .NewRequest (http .MethodPost , "/" , strings .NewReader (userForm ))
214223 rec := httptest .NewRecorder ()
@@ -336,14 +345,16 @@ func TestBindUnmarshalTextPtr(t *testing.T) {
336345}
337346
338347func TestBindMultipartForm (t * testing.T ) {
339- body := new (bytes.Buffer )
340- mw := multipart .NewWriter (body )
348+ bodyBuffer := new (bytes.Buffer )
349+ mw := multipart .NewWriter (bodyBuffer )
341350 mw .WriteField ("id" , "1" )
342351 mw .WriteField ("name" , "Jon Snow" )
343352 mw .Close ()
353+ body := bodyBuffer .Bytes ()
344354
345355 assert := assert .New (t )
346- testBindOkay (assert , body , mw .FormDataContentType ())
356+ testBindOkay (assert , bytes .NewReader (body ), nil , mw .FormDataContentType ())
357+ testBindOkay (assert , bytes .NewReader (body ), dummyQuery , mw .FormDataContentType ())
347358}
348359
349360func TestBindUnsupportedMediaType (t * testing.T ) {
@@ -547,9 +558,13 @@ func assertBindTestStruct(a *assert.Assertions, ts *bindTestStruct) {
547558 a .Equal ("" , ts .GetCantSet ())
548559}
549560
550- func testBindOkay (assert * assert.Assertions , r io.Reader , ctype string ) {
561+ func testBindOkay (assert * assert.Assertions , r io.Reader , query url. Values , ctype string ) {
551562 e := New ()
552- req := httptest .NewRequest (http .MethodPost , "/" , r )
563+ path := "/"
564+ if len (query ) > 0 {
565+ path += "?" + query .Encode ()
566+ }
567+ req := httptest .NewRequest (http .MethodPost , path , r )
553568 rec := httptest .NewRecorder ()
554569 c := e .NewContext (req , rec )
555570 req .Header .Set (HeaderContentType , ctype )
@@ -561,6 +576,25 @@ func testBindOkay(assert *assert.Assertions, r io.Reader, ctype string) {
561576 }
562577}
563578
579+ func testBindArrayOkay (assert * assert.Assertions , r io.Reader , query url.Values , ctype string ) {
580+ e := New ()
581+ path := "/"
582+ if len (query ) > 0 {
583+ path += "?" + query .Encode ()
584+ }
585+ req := httptest .NewRequest (http .MethodPost , path , r )
586+ rec := httptest .NewRecorder ()
587+ c := e .NewContext (req , rec )
588+ req .Header .Set (HeaderContentType , ctype )
589+ u := []user {}
590+ err := c .Bind (& u )
591+ if assert .NoError (err ) {
592+ assert .Equal (1 , len (u ))
593+ assert .Equal (1 , u [0 ].ID )
594+ assert .Equal ("Jon Snow" , u [0 ].Name )
595+ }
596+ }
597+
564598func testBindError (assert * assert.Assertions , r io.Reader , ctype string , expectedInternal error ) {
565599 e := New ()
566600 req := httptest .NewRequest (http .MethodPost , "/" , r )
@@ -679,15 +713,16 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
679713 expect : & Opts {ID : 0 , Node : "xxx" }, // query binding has already modified bind target
680714 expectError : "code=400, message=Unmarshal type error: expected=echo.Opts, got=array, field=, offset=1, internal=json: cannot unmarshal array into Go value of type echo.Opts" ,
681715 },
682- { // binding query params interferes with body. b.BindBody() should be used to bind only body to slice
683- name : "nok , GET query params bind failure - trying to bind json array to slice " ,
716+ { // query param is ignored as we do not know where exactly to bind it in slice
717+ name : "ok , GET bind to struct slice, ignore query param " ,
684718 givenMethod : http .MethodGet ,
685719 givenURL : "/api/real_node/endpoint?node=xxx" ,
686720 givenContent : strings .NewReader (`[{"id": 1}]` ),
687721 whenNoPathParams : true ,
688722 whenBindTarget : & []Opts {},
689- expect : & []Opts {},
690- expectError : "code=400, message=binding element must be a struct, internal=binding element must be a struct" ,
723+ expect : & []Opts {
724+ {ID : 1 , Node : "" },
725+ },
691726 },
692727 { // binding query params interferes with body. b.BindBody() should be used to bind only body to slice
693728 name : "ok, POST binding to slice should not be affected query params types" ,
@@ -699,14 +734,15 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
699734 expect : & []Opts {{ID : 1 }},
700735 expectError : "" ,
701736 },
702- { // binding path params interferes with body. b.BindBody() should be used to bind only body to slice
703- name : "nok , GET path params bind failure - trying to bind json array to slice " ,
737+ { // path param is ignored as we do not know where exactly to bind it in slice
738+ name : "ok , GET bind to struct slice, ignore path param " ,
704739 givenMethod : http .MethodGet ,
705740 givenURL : "/api/real_node/endpoint?node=xxx" ,
706741 givenContent : strings .NewReader (`[{"id": 1}]` ),
707742 whenBindTarget : & []Opts {},
708- expect : & []Opts {},
709- expectError : "code=400, message=binding element must be a struct, internal=binding element must be a struct" ,
743+ expect : & []Opts {
744+ {ID : 1 , Node : "" },
745+ },
710746 },
711747 {
712748 name : "ok, GET body bind json array to slice" ,
0 commit comments