@@ -559,7 +559,7 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
559
559
// binding is done in steps and one source could overwrite previous source binded data
560
560
// these tests are to document this behaviour and detect further possible regressions when bind implementation is changed
561
561
562
- type Node struct {
562
+ type Opts struct {
563
563
ID int `json:"id"`
564
564
Node string `json:"node"`
565
565
}
@@ -575,59 +575,105 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
575
575
expectError string
576
576
}{
577
577
{
578
- name : "ok, POST bind to struct with: path param + query param + empty body" ,
578
+ name : "ok, POST bind to struct with: path param + query param + body" ,
579
579
givenMethod : http .MethodPost ,
580
580
givenURL : "/api/real_node/endpoint?node=xxx" ,
581
581
givenContent : strings .NewReader (`{"id": 1}` ),
582
- expect : & Node {ID : 1 , Node : "xxx" }, // in current implementation query params has higher priority than path params
582
+ expect : & Opts {ID : 1 , Node : "node_from_path" }, // query params are not used, node is filled from path
583
+ },
584
+ {
585
+ name : "ok, PUT bind to struct with: path param + query param + body" ,
586
+ givenMethod : http .MethodPut ,
587
+ givenURL : "/api/real_node/endpoint?node=xxx" ,
588
+ givenContent : strings .NewReader (`{"id": 1}` ),
589
+ expect : & Opts {ID : 1 , Node : "node_from_path" }, // query params are not used
590
+ },
591
+ {
592
+ name : "ok, GET bind to struct with: path param + query param + body" ,
593
+ givenMethod : http .MethodGet ,
594
+ givenURL : "/api/real_node/endpoint?node=xxx" ,
595
+ givenContent : strings .NewReader (`{"id": 1}` ),
596
+ expect : & Opts {ID : 1 , Node : "xxx" }, // query overwrites previous path value
597
+ },
598
+ {
599
+ name : "ok, GET bind to struct with: path param + query param + body" ,
600
+ givenMethod : http .MethodGet ,
601
+ givenURL : "/api/real_node/endpoint?node=xxx" ,
602
+ givenContent : strings .NewReader (`{"id": 1, "node": "zzz"}` ),
603
+ expect : & Opts {ID : 1 , Node : "zzz" }, // body is binded last and overwrites previous (path,query) values
604
+ },
605
+ {
606
+ name : "ok, DELETE bind to struct with: path param + query param + body" ,
607
+ givenMethod : http .MethodDelete ,
608
+ givenURL : "/api/real_node/endpoint?node=xxx" ,
609
+ givenContent : strings .NewReader (`{"id": 1, "node": "zzz"}` ),
610
+ expect : & Opts {ID : 1 , Node : "zzz" }, // for DELETE body is binded after query params
583
611
},
584
612
{
585
- name : "ok, POST bind to struct with: path param + empty body" ,
613
+ name : "ok, POST bind to struct with: path param + body" ,
586
614
givenMethod : http .MethodPost ,
587
615
givenURL : "/api/real_node/endpoint" ,
588
616
givenContent : strings .NewReader (`{"id": 1}` ),
589
- expect : & Node {ID : 1 , Node : "real_node " },
617
+ expect : & Opts {ID : 1 , Node : "node_from_path " },
590
618
},
591
619
{
592
620
name : "ok, POST bind to struct with path + query + body = body has priority" ,
593
621
givenMethod : http .MethodPost ,
594
622
givenURL : "/api/real_node/endpoint?node=xxx" ,
595
623
givenContent : strings .NewReader (`{"id": 1, "node": "zzz"}` ),
596
- expect : & Node {ID : 1 , Node : "zzz" }, // field value from content has higher priority
624
+ expect : & Opts {ID : 1 , Node : "zzz" }, // field value from content has higher priority
597
625
},
598
626
{
599
627
name : "nok, POST body bind failure" ,
600
628
givenMethod : http .MethodPost ,
601
629
givenURL : "/api/real_node/endpoint?node=xxx" ,
602
630
givenContent : strings .NewReader (`{` ),
603
- expect : & Node {ID : 0 , Node : "xxx " }, // query binding has already modified bind target
631
+ expect : & Opts {ID : 0 , Node : "node_from_path " }, // query binding has already modified bind target
604
632
expectError : "code=400, message=unexpected EOF, internal=unexpected EOF" ,
605
633
},
634
+ {
635
+ name : "nok, GET with body bind failure when types are not convertible" ,
636
+ givenMethod : http .MethodGet ,
637
+ givenURL : "/api/real_node/endpoint?id=nope" ,
638
+ givenContent : strings .NewReader (`{"id": 1, "node": "zzz"}` ),
639
+ expect : & Opts {ID : 0 , Node : "node_from_path" }, // path params binding has already modified bind target
640
+ expectError : "code=400, message=strconv.ParseInt: parsing \" nope\" : invalid syntax, internal=strconv.ParseInt: parsing \" nope\" : invalid syntax" ,
641
+ },
606
642
{
607
643
name : "nok, GET body bind failure - trying to bind json array to struct" ,
608
644
givenMethod : http .MethodGet ,
609
645
givenURL : "/api/real_node/endpoint?node=xxx" ,
610
646
givenContent : strings .NewReader (`[{"id": 1}]` ),
611
- expect : & Node {ID : 0 , Node : "xxx" }, // query binding has already modified bind target
612
- expectError : "code=400, message=Unmarshal type error: expected=echo.Node , got=array, field=, offset=1, internal=json: cannot unmarshal array into Go value of type echo.Node " ,
647
+ expect : & Opts {ID : 0 , Node : "xxx" }, // query binding has already modified bind target
648
+ 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 " ,
613
649
},
614
650
{ // binding query params interferes with body. b.BindBody() should be used to bind only body to slice
615
651
name : "nok, GET query params bind failure - trying to bind json array to slice" ,
616
652
givenMethod : http .MethodGet ,
617
653
givenURL : "/api/real_node/endpoint?node=xxx" ,
618
654
givenContent : strings .NewReader (`[{"id": 1}]` ),
619
655
whenNoPathParams : true ,
620
- whenBindTarget : & []Node {},
621
- expect : & []Node {},
656
+ whenBindTarget : & []Opts {},
657
+ expect : & []Opts {},
622
658
expectError : "code=400, message=binding element must be a struct, internal=binding element must be a struct" ,
623
659
},
660
+ { // binding query params interferes with body. b.BindBody() should be used to bind only body to slice
661
+ name : "ok, POST binding to slice should not be affected query params types" ,
662
+ givenMethod : http .MethodPost ,
663
+ givenURL : "/api/real_node/endpoint?id=nope&node=xxx" ,
664
+ givenContent : strings .NewReader (`[{"id": 1}]` ),
665
+ whenNoPathParams : true ,
666
+ whenBindTarget : & []Opts {},
667
+ expect : & []Opts {{ID : 1 }},
668
+ expectError : "" ,
669
+ },
624
670
{ // binding path params interferes with body. b.BindBody() should be used to bind only body to slice
625
671
name : "nok, GET path params bind failure - trying to bind json array to slice" ,
626
672
givenMethod : http .MethodGet ,
627
673
givenURL : "/api/real_node/endpoint?node=xxx" ,
628
674
givenContent : strings .NewReader (`[{"id": 1}]` ),
629
- whenBindTarget : & []Node {},
630
- expect : & []Node {},
675
+ whenBindTarget : & []Opts {},
676
+ expect : & []Opts {},
631
677
expectError : "code=400, message=binding element must be a struct, internal=binding element must be a struct" ,
632
678
},
633
679
{
@@ -636,8 +682,8 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
636
682
givenURL : "/api/real_node/endpoint" ,
637
683
givenContent : strings .NewReader (`[{"id": 1}]` ),
638
684
whenNoPathParams : true ,
639
- whenBindTarget : & []Node {},
640
- expect : & []Node {{ID : 1 , Node : "" }},
685
+ whenBindTarget : & []Opts {},
686
+ expect : & []Opts {{ID : 1 , Node : "" }},
641
687
expectError : "" ,
642
688
},
643
689
}
@@ -653,14 +699,14 @@ func TestDefaultBinder_BindToStructFromMixedSources(t *testing.T) {
653
699
654
700
if ! tc .whenNoPathParams {
655
701
c .SetParamNames ("node" )
656
- c .SetParamValues ("real_node " )
702
+ c .SetParamValues ("node_from_path " )
657
703
}
658
704
659
705
var bindTarget interface {}
660
706
if tc .whenBindTarget != nil {
661
707
bindTarget = tc .whenBindTarget
662
708
} else {
663
- bindTarget = & Node {}
709
+ bindTarget = & Opts {}
664
710
}
665
711
b := new (DefaultBinder )
666
712
0 commit comments