Skip to content

Commit abc8bd3

Browse files
committed
chore(binding): Update priority of the parameter
Change-Id: I9245ba0c2bc05d46b254af914e3f06f0930c3640
1 parent 7efa838 commit abc8bd3

File tree

5 files changed

+107
-108
lines changed

5 files changed

+107
-108
lines changed

binding/README.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,14 @@ The parameter position in HTTP request:
9797
- Expression `required` or `req` indicates that the parameter is required
9898
- If no position is tagged, try bind parameters from the body when the request has body,
9999
<br>otherwise try bind from the URL query
100-
- When there are multiple tags, the order in which to try to bind is:
100+
- When there are multiple tags or no tags, the order in which to try to bind is:
101101
1. path
102-
2. query
103-
3. raw_body
104-
4. form
105-
5. protobuf
106-
6. json
107-
7. header
108-
8. cookie
102+
2. form
103+
3. query
104+
4. cookie
105+
5. header
106+
6. protobuf
107+
7. json
109108

110109
## Type Unmarshalor
111110

binding/bind.go

Lines changed: 29 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -129,53 +129,25 @@ func (b *Binding) bind(structPointer interface{}, req *http.Request, pathParams
129129
for i, info := range param.tagInfos {
130130
var found bool
131131
switch info.paramIn {
132-
case query:
133-
found, err = param.bindQuery(info, expr, queryValues)
134132
case path:
135133
found, err = param.bindPath(info, expr, pathParams)
136-
case header:
137-
found, err = param.bindHeader(info, expr, req.Header)
134+
case query:
135+
found, err = param.bindQuery(info, expr, queryValues)
138136
case cookie:
139137
err = param.bindCookie(info, expr, cookies)
140138
found = err == nil
141-
case raw_body:
142-
err = param.bindRawBody(info, expr, bodyBytes)
143-
found = err == nil
139+
case header:
140+
found, err = param.bindHeader(info, expr, req.Header)
144141
case form, json, protobuf:
145142
if info.paramIn == in(bodyCodec) {
146143
found, err = param.bindOrRequireBody(info, expr, bodyCodec, bodyString, postForm)
147144
} else if info.required {
148145
found = false
149146
err = info.requiredError
150147
}
151-
case auto:
152-
// Try bind parameters from the body when the request has body,
153-
// otherwise try bind from the URL query
154-
if len(bodyBytes) == 0 {
155-
if !param.omitIns[query] {
156-
if queryValues == nil {
157-
queryValues = req.URL.Query()
158-
}
159-
found, err = param.bindQuery(info, expr, queryValues)
160-
}
161-
} else {
162-
switch bodyCodec {
163-
case bodyForm:
164-
if !param.omitIns[form] {
165-
found, err = param.bindMapStrings(info, expr, postForm)
166-
}
167-
case bodyJSON:
168-
if !param.omitIns[json] {
169-
err = param.checkRequireJSON(info, expr, bodyString, false)
170-
found = err == nil
171-
}
172-
case bodyProtobuf:
173-
if !param.omitIns[protobuf] {
174-
err = param.checkRequireProtobuf(info, expr, false)
175-
found = err == nil
176-
}
177-
}
178-
}
148+
case raw_body:
149+
err = param.bindRawBody(info, expr, bodyBytes)
150+
found = err == nil
179151
}
180152
if found && err == nil {
181153
break
@@ -236,36 +208,27 @@ func (b *Binding) getOrPrepareReceiver(value reflect.Value) (*receiver, error) {
236208
tagInfos := [maxIn]*tagInfo{}
237209
L:
238210
for _, tagKV := range tagKVs {
239-
paramIn := auto
211+
paramIn := undefined
240212
switch tagKV.name {
241213
case b.config.Validator:
242214
recv.hasVd = true
243215
continue L
244-
245-
case b.config.Query:
246-
recv.hasQuery = true
247-
paramIn = query
248216
case b.config.PathParam:
249-
recv.hasPath = true
250217
paramIn = path
251-
case b.config.Header:
252-
paramIn = header
253-
case b.config.Cookie:
254-
recv.hasCookie = true
255-
paramIn = cookie
256-
case b.config.RawBody:
257-
recv.hasBody = true
258-
paramIn = raw_body
259218
case b.config.FormBody:
260-
recv.hasBody = true
261219
paramIn = form
220+
case b.config.Query:
221+
paramIn = query
222+
case b.config.Cookie:
223+
paramIn = cookie
224+
case b.config.Header:
225+
paramIn = header
262226
case b.config.protobufBody:
263-
recv.hasBody = true
264227
paramIn = protobuf
265228
case b.config.jsonBody:
266-
recv.hasBody = true
267229
paramIn = json
268-
230+
case b.config.RawBody:
231+
paramIn = raw_body
269232
default:
270233
continue L
271234
}
@@ -275,18 +238,26 @@ func (b *Binding) getOrPrepareReceiver(value reflect.Value) (*receiver, error) {
275238
if info != nil {
276239
if info.paramName == "-" {
277240
p.omitIns[in(i)] = true
241+
recv.assginIn(in(i), false)
278242
} else {
279243
info.paramIn = in(i)
280244
p.tagInfos = append(p.tagInfos, info)
245+
recv.assginIn(in(i), true)
281246
}
282247
}
283248
}
284249
if len(p.tagInfos) == 0 {
285-
p.tagInfos = append(p.tagInfos, &tagInfo{
286-
paramIn: auto,
287-
paramName: p.structField.Name,
288-
})
289-
recv.hasBody = true
250+
for _, i := range sortedDefaultIn {
251+
if p.omitIns[i] {
252+
recv.assginIn(i, false)
253+
continue
254+
}
255+
p.tagInfos = append(p.tagInfos, &tagInfo{
256+
paramIn: i,
257+
paramName: p.structField.Name,
258+
})
259+
recv.assginIn(i, true)
260+
}
290261
}
291262
if !recv.hasVd {
292263
_, recv.hasVd = tagKVs.lookup(b.config.Validator)

binding/bind_test.go

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func TestQueryString(t *testing.T) {
6767
assert.EqualError(t, err, "binding X.E: parameter type does not match binding data")
6868
binder.SetLooseZeroMode(true)
6969
err = binder.BindAndValidate(recv, req, nil)
70-
assert.Nil(t, err)
70+
assert.NoError(t, err)
7171
assert.Equal(t, 0, ***(*(**recv.X).E)[0])
7272
assert.Equal(t, 2, ***(*(**recv.X).E)[1])
7373
assert.Equal(t, []string{"a1", "a2"}, (**recv.X).A)
@@ -106,7 +106,7 @@ func TestQueryNum(t *testing.T) {
106106
recv := new(Recv)
107107
binder := binding.New(nil)
108108
err := binder.BindAndValidate(recv, req, nil)
109-
assert.Nil(t, err)
109+
assert.NoError(t, err)
110110
assert.Equal(t, []int{11, 12}, (**recv.X).A)
111111
assert.Equal(t, int32(21), (**recv.X).B)
112112
assert.Equal(t, &[]uint16{31, 32}, (**recv.X).C)
@@ -139,7 +139,7 @@ func TestHeaderString(t *testing.T) {
139139
recv := new(Recv)
140140
binder := binding.New(nil)
141141
err := binder.BindAndValidate(recv, req, nil)
142-
assert.Nil(t, err)
142+
assert.NoError(t, err)
143143
assert.Equal(t, []string{"a1", "a2"}, (**recv.X).A)
144144
assert.Equal(t, "b1", (**recv.X).B)
145145
assert.Equal(t, []string{"c1", "c2"}, *(**recv.X).C)
@@ -172,7 +172,7 @@ func TestHeaderNum(t *testing.T) {
172172
recv := new(Recv)
173173
binder := binding.New(nil)
174174
err := binder.BindAndValidate(recv, req, nil)
175-
assert.Nil(t, err)
175+
assert.NoError(t, err)
176176
assert.Equal(t, []int{11, 12}, (**recv.X).A)
177177
assert.Equal(t, int32(21), (**recv.X).B)
178178
assert.Equal(t, &[]uint16{31, 32}, (**recv.X).C)
@@ -206,7 +206,7 @@ func TestCookieString(t *testing.T) {
206206
recv := new(Recv)
207207
binder := binding.New(nil)
208208
err := binder.BindAndValidate(recv, req, nil)
209-
assert.Nil(t, err)
209+
assert.NoError(t, err)
210210
assert.Equal(t, []string{"a1", "a2"}, (**recv.X).A)
211211
assert.Equal(t, "b1", (**recv.X).B)
212212
assert.Equal(t, []string{"c1", "c2"}, *(**recv.X).C)
@@ -240,7 +240,7 @@ func TestCookieNum(t *testing.T) {
240240
recv := new(Recv)
241241
binder := binding.New(nil)
242242
err := binder.BindAndValidate(recv, req, nil)
243-
assert.Nil(t, err)
243+
assert.NoError(t, err)
244244
assert.Equal(t, []int{11, 12}, (**recv.X).A)
245245
assert.Equal(t, int32(21), (**recv.X).B)
246246
assert.Equal(t, &[]uint16{31, 32}, (**recv.X).C)
@@ -281,7 +281,7 @@ func TestFormString(t *testing.T) {
281281
recv := new(Recv)
282282
binder := binding.New(nil)
283283
err := binder.BindAndValidate(recv, req, nil)
284-
assert.Nil(t, err)
284+
assert.NoError(t, err)
285285
assert.Equal(t, []string{"a1", "a2"}, (**recv.X).A)
286286
assert.Equal(t, "b1", (**recv.X).B)
287287
assert.Equal(t, []string{"c1", "c2"}, *(**recv.X).C)
@@ -323,7 +323,7 @@ func TestFormNum(t *testing.T) {
323323
recv := new(Recv)
324324
binder := binding.New(nil)
325325
err := binder.BindAndValidate(recv, req, nil)
326-
assert.Nil(t, err)
326+
assert.NoError(t, err)
327327
assert.Equal(t, []int{11, 12}, (**recv.X).A)
328328
assert.Equal(t, int32(-21), (**recv.X).B)
329329
assert.Equal(t, &[]uint16{31, 32}, (**recv.X).C)
@@ -490,7 +490,7 @@ func TestPath(t *testing.T) {
490490
recv := new(Recv)
491491
binder := binding.New(nil)
492492
err := binder.BindAndValidate(recv, req, new(testPathParams))
493-
assert.Nil(t, err)
493+
assert.NoError(t, err)
494494
assert.Equal(t, []string{"a1"}, (**recv.X).A)
495495
assert.Equal(t, int32(-21), (**recv.X).B)
496496
assert.Equal(t, &[]uint16{31}, (**recv.X).C)
@@ -504,40 +504,48 @@ func TestAuto(t *testing.T) {
504504
A string `vd:"$!=''"`
505505
B string
506506
C string
507-
D string `form:"D,required" query:"D,required"`
507+
D string `query:"D,required" form:"D,required"`
508+
E string `cookie:"e" json:"e"`
508509
}
509510
query := make(url.Values)
510511
query.Add("A", "a")
511512
query.Add("B", "b")
512513
query.Add("C", "c")
513-
query.Add("D", "d")
514-
req := newRequest("http://localhost/?"+query.Encode(), nil, nil, nil)
514+
query.Add("D", "d-from-query")
515+
contentType, bodyReader, err := httpbody.NewJSONBody(map[string]string{"e": "e-from-jsonbody"})
516+
assert.NoError(t, err)
517+
header := make(http.Header)
518+
header.Set("Content-Type", contentType)
519+
req := newRequest("http://localhost/?"+query.Encode(), header, []*http.Cookie{
520+
{Name: "e", Value: "e-from-cookie"},
521+
}, bodyReader)
515522
recv := new(Recv)
516523
binder := binding.New(nil)
517-
err := binder.BindAndValidate(recv, req, nil)
518-
assert.Nil(t, err)
524+
err = binder.BindAndValidate(recv, req, nil)
525+
assert.NoError(t, err)
519526
assert.Equal(t, "a", recv.A)
520527
assert.Equal(t, "b", recv.B)
521528
assert.Equal(t, "c", recv.C)
522-
assert.Equal(t, "d", recv.D)
529+
assert.Equal(t, "d-from-query", recv.D)
530+
assert.Equal(t, "e-from-cookie", recv.E)
523531

524532
query = make(url.Values)
525-
query.Add("A", "a")
526-
query.Add("D", "d")
533+
query.Add("D", "d-from-query")
527534
form := make(url.Values)
528535
form.Add("B", "b")
529536
form.Add("C", "c")
530-
contentType, bodyReader := httpbody.NewFormBody2(form, nil)
531-
header := make(http.Header)
537+
form.Add("D", "d-from-form")
538+
contentType, bodyReader = httpbody.NewFormBody2(form, nil)
539+
header = make(http.Header)
532540
header.Set("Content-Type", contentType)
533541
req = newRequest("http://localhost/?"+query.Encode(), header, nil, bodyReader)
534542
recv = new(Recv)
535543
err = binder.Bind(recv, req, nil)
536-
assert.Nil(t, err)
544+
assert.NoError(t, err)
537545
assert.Equal(t, "", recv.A)
538546
assert.Equal(t, "b", recv.B)
539547
assert.Equal(t, "c", recv.C)
540-
assert.Equal(t, "d", recv.D)
548+
assert.Equal(t, "d-from-form", recv.D)
541549
err = binder.Validate(recv)
542550
assert.EqualError(t, err, "validating A: fail")
543551
}
@@ -560,15 +568,15 @@ func TestTypeUnmarshal(t *testing.T) {
560568
recv := new(Recv)
561569
binder := binding.New(nil)
562570
err := binder.BindAndValidate(recv, req, nil)
563-
assert.Nil(t, err)
571+
assert.NoError(t, err)
564572
t1, err := time.Parse(time.RFC3339, "2019-09-03T18:05:24+08:00")
565-
assert.Nil(t, err)
573+
assert.NoError(t, err)
566574
assert.Equal(t, t1, recv.A)
567575
t21, err := time.Parse(time.RFC3339, "2019-09-04T14:05:24+08:00")
568-
assert.Nil(t, err)
576+
assert.NoError(t, err)
569577
assert.Equal(t, t21, *recv.B)
570578
t22, err := time.Parse(time.RFC3339, "2019-09-04T18:05:24+08:00")
571-
assert.Nil(t, err)
579+
assert.NoError(t, err)
572580
assert.Equal(t, []time.Time{t21, t22}, recv.C)
573581
t.Logf("%v", recv)
574582
}

binding/param_info.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ func (p *paramInfo) bindRawBody(info *tagInfo, expr *tagexpr.TagExpr, bodyBytes
7373
}
7474

7575
func (p *paramInfo) bindPath(info *tagInfo, expr *tagexpr.TagExpr, pathParams PathParams) (bool, error) {
76+
if pathParams == nil {
77+
return false, nil
78+
}
7679
r, found := pathParams.Get(info.paramName)
7780
if !found {
7881
if info.required {

0 commit comments

Comments
 (0)