1
2
3
4
5 package binding
6
7 import (
8 "bytes"
9 "encoding/json"
10 "errors"
11 "io"
12 "mime/multipart"
13 "net/http"
14 "os"
15 "reflect"
16 "strconv"
17 "strings"
18 "testing"
19 "time"
20
21 "github.com/gin-gonic/gin/testdata/protoexample"
22 "github.com/stretchr/testify/assert"
23 "google.golang.org/protobuf/proto"
24 )
25
26 type appkey struct {
27 Appkey string `json:"appkey" form:"appkey"`
28 }
29
30 type QueryTest struct {
31 Page int `json:"page" form:"page"`
32 Size int `json:"size" form:"size"`
33 appkey
34 }
35
36 type FooStruct struct {
37 Foo string `msgpack:"foo" json:"foo" form:"foo" xml:"foo" binding:"required,max=32"`
38 }
39
40 type FooBarStruct struct {
41 FooStruct
42 Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
43 }
44
45 type FooBarFileStruct struct {
46 FooBarStruct
47 File *multipart.FileHeader `form:"file" binding:"required"`
48 }
49
50 type FooBarFileFailStruct struct {
51 FooBarStruct
52 File *multipart.FileHeader `invalid_name:"file" binding:"required"`
53
54 data *multipart.FileHeader `form:"data" binding:"required"`
55 }
56
57 type FooDefaultBarStruct struct {
58 FooStruct
59 Bar string `msgpack:"bar" json:"bar" form:"bar,default=hello" xml:"bar" binding:"required"`
60 }
61
62 type FooStructUseNumber struct {
63 Foo any `json:"foo" binding:"required"`
64 }
65
66 type FooStructDisallowUnknownFields struct {
67 Foo any `json:"foo" binding:"required"`
68 }
69
70 type FooBarStructForTimeType struct {
71 TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
72 TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
73 CreateTime time.Time `form:"createTime" time_format:"unixNano"`
74 UnixTime time.Time `form:"unixTime" time_format:"unix"`
75 }
76
77 type FooStructForTimeTypeNotUnixFormat struct {
78 CreateTime time.Time `form:"createTime" time_format:"unixNano"`
79 UnixTime time.Time `form:"unixTime" time_format:"unix"`
80 }
81
82 type FooStructForTimeTypeNotFormat struct {
83 TimeFoo time.Time `form:"time_foo"`
84 }
85
86 type FooStructForTimeTypeFailFormat struct {
87 TimeFoo time.Time `form:"time_foo" time_format:"2017-11-15"`
88 }
89
90 type FooStructForTimeTypeFailLocation struct {
91 TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_location:"/asia/chongqing"`
92 }
93
94 type FooStructForMapType struct {
95 MapFoo map[string]any `form:"map_foo"`
96 }
97
98 type FooStructForIgnoreFormTag struct {
99 Foo *string `form:"-"`
100 }
101
102 type InvalidNameType struct {
103 TestName string `invalid_name:"test_name"`
104 }
105
106 type InvalidNameMapType struct {
107 TestName struct {
108 MapFoo map[string]any `form:"map_foo"`
109 }
110 }
111
112 type FooStructForSliceType struct {
113 SliceFoo []int `form:"slice_foo"`
114 }
115
116 type FooStructForStructType struct {
117 StructFoo struct {
118 Idx int `form:"idx"`
119 }
120 }
121
122 type FooStructForStructPointerType struct {
123 StructPointerFoo *struct {
124 Name string `form:"name"`
125 }
126 }
127
128 type FooStructForSliceMapType struct {
129
130 SliceMapFoo []map[string]any `form:"slice_map_foo"`
131 }
132
133 type FooStructForBoolType struct {
134 BoolFoo bool `form:"bool_foo"`
135 }
136
137 type FooStructForStringPtrType struct {
138 PtrFoo *string `form:"ptr_foo"`
139 PtrBar *string `form:"ptr_bar" binding:"required"`
140 }
141
142 type FooStructForMapPtrType struct {
143 PtrBar *map[string]any `form:"ptr_bar"`
144 }
145
146 func TestBindingDefault(t *testing.T) {
147 assert.Equal(t, Form, Default("GET", ""))
148 assert.Equal(t, Form, Default("GET", MIMEJSON))
149
150 assert.Equal(t, JSON, Default("POST", MIMEJSON))
151 assert.Equal(t, JSON, Default("PUT", MIMEJSON))
152
153 assert.Equal(t, XML, Default("POST", MIMEXML))
154 assert.Equal(t, XML, Default("PUT", MIMEXML2))
155
156 assert.Equal(t, Form, Default("POST", MIMEPOSTForm))
157 assert.Equal(t, Form, Default("PUT", MIMEPOSTForm))
158
159 assert.Equal(t, FormMultipart, Default("POST", MIMEMultipartPOSTForm))
160 assert.Equal(t, FormMultipart, Default("PUT", MIMEMultipartPOSTForm))
161
162 assert.Equal(t, ProtoBuf, Default("POST", MIMEPROTOBUF))
163 assert.Equal(t, ProtoBuf, Default("PUT", MIMEPROTOBUF))
164
165 assert.Equal(t, YAML, Default("POST", MIMEYAML))
166 assert.Equal(t, YAML, Default("PUT", MIMEYAML))
167
168 assert.Equal(t, TOML, Default("POST", MIMETOML))
169 assert.Equal(t, TOML, Default("PUT", MIMETOML))
170 }
171
172 func TestBindingJSONNilBody(t *testing.T) {
173 var obj FooStruct
174 req, _ := http.NewRequest(http.MethodPost, "/", nil)
175 err := JSON.Bind(req, &obj)
176 assert.Error(t, err)
177 }
178
179 func TestBindingJSON(t *testing.T) {
180 testBodyBinding(t,
181 JSON, "json",
182 "/", "/",
183 `{"foo": "bar"}`, `{"bar": "foo"}`)
184 }
185
186 func TestBindingJSONSlice(t *testing.T) {
187 EnableDecoderDisallowUnknownFields = true
188 defer func() {
189 EnableDecoderDisallowUnknownFields = false
190 }()
191
192 testBodyBindingSlice(t, JSON, "json", "/", "/", `[]`, ``)
193 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{}]`)
194 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"foo": ""}]`)
195 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"foo": 123}]`)
196 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"bar": 123}]`)
197 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"foo": "123456789012345678901234567890123"}]`)
198 }
199
200 func TestBindingJSONUseNumber(t *testing.T) {
201 testBodyBindingUseNumber(t,
202 JSON, "json",
203 "/", "/",
204 `{"foo": 123}`, `{"bar": "foo"}`)
205 }
206
207 func TestBindingJSONUseNumber2(t *testing.T) {
208 testBodyBindingUseNumber2(t,
209 JSON, "json",
210 "/", "/",
211 `{"foo": 123}`, `{"bar": "foo"}`)
212 }
213
214 func TestBindingJSONDisallowUnknownFields(t *testing.T) {
215 testBodyBindingDisallowUnknownFields(t, JSON,
216 "/", "/",
217 `{"foo": "bar"}`, `{"foo": "bar", "what": "this"}`)
218 }
219
220 func TestBindingJSONStringMap(t *testing.T) {
221 testBodyBindingStringMap(t, JSON,
222 "/", "/",
223 `{"foo": "bar", "hello": "world"}`, `{"num": 2}`)
224 }
225
226 func TestBindingForm(t *testing.T) {
227 testFormBinding(t, "POST",
228 "/", "/",
229 "foo=bar&bar=foo", "bar2=foo")
230 }
231
232 func TestBindingForm2(t *testing.T) {
233 testFormBinding(t, "GET",
234 "/?foo=bar&bar=foo", "/?bar2=foo",
235 "", "")
236 }
237
238 func TestBindingFormEmbeddedStruct(t *testing.T) {
239 testFormBindingEmbeddedStruct(t, "POST",
240 "/", "/",
241 "page=1&size=2&appkey=test-appkey", "bar2=foo")
242 }
243
244 func TestBindingFormEmbeddedStruct2(t *testing.T) {
245 testFormBindingEmbeddedStruct(t, "GET",
246 "/?page=1&size=2&appkey=test-appkey", "/?bar2=foo",
247 "", "")
248 }
249
250 func TestBindingFormDefaultValue(t *testing.T) {
251 testFormBindingDefaultValue(t, "POST",
252 "/", "/",
253 "foo=bar", "bar2=foo")
254 }
255
256 func TestBindingFormDefaultValue2(t *testing.T) {
257 testFormBindingDefaultValue(t, "GET",
258 "/?foo=bar", "/?bar2=foo",
259 "", "")
260 }
261
262 func TestBindingFormForTime(t *testing.T) {
263 testFormBindingForTime(t, "POST",
264 "/", "/",
265 "time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "bar2=foo")
266 testFormBindingForTimeNotUnixFormat(t, "POST",
267 "/", "/",
268 "time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
269 testFormBindingForTimeNotFormat(t, "POST",
270 "/", "/",
271 "time_foo=2017-11-15", "bar2=foo")
272 testFormBindingForTimeFailFormat(t, "POST",
273 "/", "/",
274 "time_foo=2017-11-15", "bar2=foo")
275 testFormBindingForTimeFailLocation(t, "POST",
276 "/", "/",
277 "time_foo=2017-11-15", "bar2=foo")
278 }
279
280 func TestBindingFormForTime2(t *testing.T) {
281 testFormBindingForTime(t, "GET",
282 "/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "/?bar2=foo",
283 "", "")
284 testFormBindingForTimeNotUnixFormat(t, "POST",
285 "/", "/",
286 "time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
287 testFormBindingForTimeNotFormat(t, "GET",
288 "/?time_foo=2017-11-15", "/?bar2=foo",
289 "", "")
290 testFormBindingForTimeFailFormat(t, "GET",
291 "/?time_foo=2017-11-15", "/?bar2=foo",
292 "", "")
293 testFormBindingForTimeFailLocation(t, "GET",
294 "/?time_foo=2017-11-15", "/?bar2=foo",
295 "", "")
296 }
297
298 func TestFormBindingIgnoreField(t *testing.T) {
299 testFormBindingIgnoreField(t, "POST",
300 "/", "/",
301 "-=bar", "")
302 }
303
304 func TestBindingFormInvalidName(t *testing.T) {
305 testFormBindingInvalidName(t, "POST",
306 "/", "/",
307 "test_name=bar", "bar2=foo")
308 }
309
310 func TestBindingFormInvalidName2(t *testing.T) {
311 testFormBindingInvalidName2(t, "POST",
312 "/", "/",
313 "map_foo=bar", "bar2=foo")
314 }
315
316 func TestBindingFormForType(t *testing.T) {
317 testFormBindingForType(t, "POST",
318 "/", "/",
319 "map_foo={\"bar\":123}", "map_foo=1", "Map")
320
321 testFormBindingForType(t, "POST",
322 "/", "/",
323 "slice_foo=1&slice_foo=2", "bar2=1&bar2=2", "Slice")
324
325 testFormBindingForType(t, "GET",
326 "/?slice_foo=1&slice_foo=2", "/?bar2=1&bar2=2",
327 "", "", "Slice")
328
329 testFormBindingForType(t, "POST",
330 "/", "/",
331 "slice_map_foo=1&slice_map_foo=2", "bar2=1&bar2=2", "SliceMap")
332
333 testFormBindingForType(t, "GET",
334 "/?slice_map_foo=1&slice_map_foo=2", "/?bar2=1&bar2=2",
335 "", "", "SliceMap")
336
337 testFormBindingForType(t, "POST",
338 "/", "/",
339 "ptr_bar=test", "bar2=test", "Ptr")
340
341 testFormBindingForType(t, "GET",
342 "/?ptr_bar=test", "/?bar2=test",
343 "", "", "Ptr")
344
345 testFormBindingForType(t, "POST",
346 "/", "/",
347 "idx=123", "id1=1", "Struct")
348
349 testFormBindingForType(t, "GET",
350 "/?idx=123", "/?id1=1",
351 "", "", "Struct")
352
353 testFormBindingForType(t, "POST",
354 "/", "/",
355 "name=thinkerou", "name1=ou", "StructPointer")
356
357 testFormBindingForType(t, "GET",
358 "/?name=thinkerou", "/?name1=ou",
359 "", "", "StructPointer")
360 }
361
362 func TestBindingFormStringMap(t *testing.T) {
363 testBodyBindingStringMap(t, Form,
364 "/", "",
365 `foo=bar&hello=world`, "")
366
367 testBodyBindingStringMap(t, Form,
368 "/", "",
369 `foo=something&foo=bar&hello=world`, "")
370 }
371
372 func TestBindingFormStringSliceMap(t *testing.T) {
373 obj := make(map[string][]string)
374 req := requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
375 req.Header.Add("Content-Type", MIMEPOSTForm)
376 err := Form.Bind(req, &obj)
377 assert.NoError(t, err)
378 assert.NotNil(t, obj)
379 assert.Len(t, obj, 2)
380 target := map[string][]string{
381 "foo": {"something", "bar"},
382 "hello": {"world"},
383 }
384 assert.True(t, reflect.DeepEqual(obj, target))
385
386 objInvalid := make(map[string][]int)
387 req = requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
388 req.Header.Add("Content-Type", MIMEPOSTForm)
389 err = Form.Bind(req, &objInvalid)
390 assert.Error(t, err)
391 }
392
393 func TestBindingQuery(t *testing.T) {
394 testQueryBinding(t, "POST",
395 "/?foo=bar&bar=foo", "/",
396 "foo=unused", "bar2=foo")
397 }
398
399 func TestBindingQuery2(t *testing.T) {
400 testQueryBinding(t, "GET",
401 "/?foo=bar&bar=foo", "/?bar2=foo",
402 "foo=unused", "")
403 }
404
405 func TestBindingQueryFail(t *testing.T) {
406 testQueryBindingFail(t, "POST",
407 "/?map_foo=", "/",
408 "map_foo=unused", "bar2=foo")
409 }
410
411 func TestBindingQueryFail2(t *testing.T) {
412 testQueryBindingFail(t, "GET",
413 "/?map_foo=", "/?bar2=foo",
414 "map_foo=unused", "")
415 }
416
417 func TestBindingQueryBoolFail(t *testing.T) {
418 testQueryBindingBoolFail(t, "GET",
419 "/?bool_foo=fasl", "/?bar2=foo",
420 "bool_foo=unused", "")
421 }
422
423 func TestBindingQueryStringMap(t *testing.T) {
424 b := Query
425
426 obj := make(map[string]string)
427 req := requestWithBody("GET", "/?foo=bar&hello=world", "")
428 err := b.Bind(req, &obj)
429 assert.NoError(t, err)
430 assert.NotNil(t, obj)
431 assert.Len(t, obj, 2)
432 assert.Equal(t, "bar", obj["foo"])
433 assert.Equal(t, "world", obj["hello"])
434
435 obj = make(map[string]string)
436 req = requestWithBody("GET", "/?foo=bar&foo=2&hello=world", "")
437 err = b.Bind(req, &obj)
438 assert.NoError(t, err)
439 assert.NotNil(t, obj)
440 assert.Len(t, obj, 2)
441 assert.Equal(t, "2", obj["foo"])
442 assert.Equal(t, "world", obj["hello"])
443 }
444
445 func TestBindingXML(t *testing.T) {
446 testBodyBinding(t,
447 XML, "xml",
448 "/", "/",
449 "<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>")
450 }
451
452 func TestBindingXMLFail(t *testing.T) {
453 testBodyBindingFail(t,
454 XML, "xml",
455 "/", "/",
456 "<map><foo>bar<foo></map>", "<map><bar>foo</bar></map>")
457 }
458
459 func TestBindingTOML(t *testing.T) {
460 testBodyBinding(t,
461 TOML, "toml",
462 "/", "/",
463 `foo="bar"`, `bar="foo"`)
464 }
465
466 func TestBindingTOMLFail(t *testing.T) {
467 testBodyBindingFail(t,
468 TOML, "toml",
469 "/", "/",
470 `foo=\n"bar"`, `bar="foo"`)
471 }
472
473 func TestBindingYAML(t *testing.T) {
474 testBodyBinding(t,
475 YAML, "yaml",
476 "/", "/",
477 `foo: bar`, `bar: foo`)
478 }
479
480 func TestBindingYAMLStringMap(t *testing.T) {
481
482 testBodyBindingStringMap(t, YAML,
483 "/", "/",
484 `{"foo": "bar", "hello": "world"}`, `{"nested": {"foo": "bar"}}`)
485 }
486
487 func TestBindingYAMLFail(t *testing.T) {
488 testBodyBindingFail(t,
489 YAML, "yaml",
490 "/", "/",
491 `foo:\nbar`, `bar: foo`)
492 }
493
494 func createFormPostRequest(t *testing.T) *http.Request {
495 req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
496 assert.NoError(t, err)
497 req.Header.Set("Content-Type", MIMEPOSTForm)
498 return req
499 }
500
501 func createDefaultFormPostRequest(t *testing.T) *http.Request {
502 req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
503 assert.NoError(t, err)
504 req.Header.Set("Content-Type", MIMEPOSTForm)
505 return req
506 }
507
508 func createFormPostRequestForMap(t *testing.T) *http.Request {
509 req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}"))
510 assert.NoError(t, err)
511 req.Header.Set("Content-Type", MIMEPOSTForm)
512 return req
513 }
514
515 func createFormPostRequestForMapFail(t *testing.T) *http.Request {
516 req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello"))
517 assert.NoError(t, err)
518 req.Header.Set("Content-Type", MIMEPOSTForm)
519 return req
520 }
521
522 func createFormFilesMultipartRequest(t *testing.T) *http.Request {
523 boundary := "--testboundary"
524 body := new(bytes.Buffer)
525 mw := multipart.NewWriter(body)
526 defer mw.Close()
527
528 assert.NoError(t, mw.SetBoundary(boundary))
529 assert.NoError(t, mw.WriteField("foo", "bar"))
530 assert.NoError(t, mw.WriteField("bar", "foo"))
531
532 f, err := os.Open("form.go")
533 assert.NoError(t, err)
534 defer f.Close()
535 fw, err1 := mw.CreateFormFile("file", "form.go")
536 assert.NoError(t, err1)
537 _, err = io.Copy(fw, f)
538 assert.NoError(t, err)
539
540 req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
541 assert.NoError(t, err2)
542 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
543
544 return req
545 }
546
547 func createFormFilesMultipartRequestFail(t *testing.T) *http.Request {
548 boundary := "--testboundary"
549 body := new(bytes.Buffer)
550 mw := multipart.NewWriter(body)
551 defer mw.Close()
552
553 assert.NoError(t, mw.SetBoundary(boundary))
554 assert.NoError(t, mw.WriteField("foo", "bar"))
555 assert.NoError(t, mw.WriteField("bar", "foo"))
556
557 f, err := os.Open("form.go")
558 assert.NoError(t, err)
559 defer f.Close()
560 fw, err1 := mw.CreateFormFile("file_foo", "form_foo.go")
561 assert.NoError(t, err1)
562 _, err = io.Copy(fw, f)
563 assert.NoError(t, err)
564
565 req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
566 assert.NoError(t, err2)
567 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
568
569 return req
570 }
571
572 func createFormMultipartRequest(t *testing.T) *http.Request {
573 boundary := "--testboundary"
574 body := new(bytes.Buffer)
575 mw := multipart.NewWriter(body)
576 defer mw.Close()
577
578 assert.NoError(t, mw.SetBoundary(boundary))
579 assert.NoError(t, mw.WriteField("foo", "bar"))
580 assert.NoError(t, mw.WriteField("bar", "foo"))
581 req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
582 assert.NoError(t, err)
583 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
584 return req
585 }
586
587 func createFormMultipartRequestForMap(t *testing.T) *http.Request {
588 boundary := "--testboundary"
589 body := new(bytes.Buffer)
590 mw := multipart.NewWriter(body)
591 defer mw.Close()
592
593 assert.NoError(t, mw.SetBoundary(boundary))
594 assert.NoError(t, mw.WriteField("map_foo", "{\"bar\":123, \"name\":\"thinkerou\", \"pai\": 3.14}"))
595 req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
596 assert.NoError(t, err)
597 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
598 return req
599 }
600
601 func createFormMultipartRequestForMapFail(t *testing.T) *http.Request {
602 boundary := "--testboundary"
603 body := new(bytes.Buffer)
604 mw := multipart.NewWriter(body)
605 defer mw.Close()
606
607 assert.NoError(t, mw.SetBoundary(boundary))
608 assert.NoError(t, mw.WriteField("map_foo", "3.14"))
609 req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
610 assert.NoError(t, err)
611 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
612 return req
613 }
614
615 func TestBindingFormPost(t *testing.T) {
616 req := createFormPostRequest(t)
617 var obj FooBarStruct
618 assert.NoError(t, FormPost.Bind(req, &obj))
619
620 assert.Equal(t, "form-urlencoded", FormPost.Name())
621 assert.Equal(t, "bar", obj.Foo)
622 assert.Equal(t, "foo", obj.Bar)
623 }
624
625 func TestBindingDefaultValueFormPost(t *testing.T) {
626 req := createDefaultFormPostRequest(t)
627 var obj FooDefaultBarStruct
628 assert.NoError(t, FormPost.Bind(req, &obj))
629
630 assert.Equal(t, "bar", obj.Foo)
631 assert.Equal(t, "hello", obj.Bar)
632 }
633
634 func TestBindingFormPostForMap(t *testing.T) {
635 req := createFormPostRequestForMap(t)
636 var obj FooStructForMapType
637 err := FormPost.Bind(req, &obj)
638 assert.NoError(t, err)
639 assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64))
640 }
641
642 func TestBindingFormPostForMapFail(t *testing.T) {
643 req := createFormPostRequestForMapFail(t)
644 var obj FooStructForMapType
645 err := FormPost.Bind(req, &obj)
646 assert.Error(t, err)
647 }
648
649 func TestBindingFormFilesMultipart(t *testing.T) {
650 req := createFormFilesMultipartRequest(t)
651 var obj FooBarFileStruct
652 err := FormMultipart.Bind(req, &obj)
653 assert.NoError(t, err)
654
655
656 f, _ := os.Open("form.go")
657 defer f.Close()
658 fileActual, _ := io.ReadAll(f)
659
660
661 mf, _ := obj.File.Open()
662 defer mf.Close()
663 fileExpect, _ := io.ReadAll(mf)
664
665 assert.Equal(t, FormMultipart.Name(), "multipart/form-data")
666 assert.Equal(t, obj.Foo, "bar")
667 assert.Equal(t, obj.Bar, "foo")
668 assert.Equal(t, fileExpect, fileActual)
669 }
670
671 func TestBindingFormFilesMultipartFail(t *testing.T) {
672 req := createFormFilesMultipartRequestFail(t)
673 var obj FooBarFileFailStruct
674 err := FormMultipart.Bind(req, &obj)
675 assert.Error(t, err)
676 }
677
678 func TestBindingFormMultipart(t *testing.T) {
679 req := createFormMultipartRequest(t)
680 var obj FooBarStruct
681 assert.NoError(t, FormMultipart.Bind(req, &obj))
682
683 assert.Equal(t, "multipart/form-data", FormMultipart.Name())
684 assert.Equal(t, "bar", obj.Foo)
685 assert.Equal(t, "foo", obj.Bar)
686 }
687
688 func TestBindingFormMultipartForMap(t *testing.T) {
689 req := createFormMultipartRequestForMap(t)
690 var obj FooStructForMapType
691 err := FormMultipart.Bind(req, &obj)
692 assert.NoError(t, err)
693 assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64))
694 assert.Equal(t, "thinkerou", obj.MapFoo["name"].(string))
695 assert.Equal(t, float64(3.14), obj.MapFoo["pai"].(float64))
696 }
697
698 func TestBindingFormMultipartForMapFail(t *testing.T) {
699 req := createFormMultipartRequestForMapFail(t)
700 var obj FooStructForMapType
701 err := FormMultipart.Bind(req, &obj)
702 assert.Error(t, err)
703 }
704
705 func TestBindingProtoBuf(t *testing.T) {
706 test := &protoexample.Test{
707 Label: proto.String("yes"),
708 }
709 data, _ := proto.Marshal(test)
710
711 testProtoBodyBinding(t,
712 ProtoBuf, "protobuf",
713 "/", "/",
714 string(data), string(data[1:]))
715 }
716
717 func TestBindingProtoBufFail(t *testing.T) {
718 test := &protoexample.Test{
719 Label: proto.String("yes"),
720 }
721 data, _ := proto.Marshal(test)
722
723 testProtoBodyBindingFail(t,
724 ProtoBuf, "protobuf",
725 "/", "/",
726 string(data), string(data[1:]))
727 }
728
729 func TestValidationFails(t *testing.T) {
730 var obj FooStruct
731 req := requestWithBody("POST", "/", `{"bar": "foo"}`)
732 err := JSON.Bind(req, &obj)
733 assert.Error(t, err)
734 }
735
736 func TestValidationDisabled(t *testing.T) {
737 backup := Validator
738 Validator = nil
739 defer func() { Validator = backup }()
740
741 var obj FooStruct
742 req := requestWithBody("POST", "/", `{"bar": "foo"}`)
743 err := JSON.Bind(req, &obj)
744 assert.NoError(t, err)
745 }
746
747 func TestRequiredSucceeds(t *testing.T) {
748 type HogeStruct struct {
749 Hoge *int `json:"hoge" binding:"required"`
750 }
751
752 var obj HogeStruct
753 req := requestWithBody("POST", "/", `{"hoge": 0}`)
754 err := JSON.Bind(req, &obj)
755 assert.NoError(t, err)
756 }
757
758 func TestRequiredFails(t *testing.T) {
759 type HogeStruct struct {
760 Hoge *int `json:"foo" binding:"required"`
761 }
762
763 var obj HogeStruct
764 req := requestWithBody("POST", "/", `{"boen": 0}`)
765 err := JSON.Bind(req, &obj)
766 assert.Error(t, err)
767 }
768
769 func TestHeaderBinding(t *testing.T) {
770 h := Header
771 assert.Equal(t, "header", h.Name())
772
773 type tHeader struct {
774 Limit int `header:"limit"`
775 }
776
777 var theader tHeader
778 req := requestWithBody("GET", "/", "")
779 req.Header.Add("limit", "1000")
780 assert.NoError(t, h.Bind(req, &theader))
781 assert.Equal(t, 1000, theader.Limit)
782
783 req = requestWithBody("GET", "/", "")
784 req.Header.Add("fail", `{fail:fail}`)
785
786 type failStruct struct {
787 Fail map[string]any `header:"fail"`
788 }
789
790 err := h.Bind(req, &failStruct{})
791 assert.Error(t, err)
792 }
793
794 func TestUriBinding(t *testing.T) {
795 b := Uri
796 assert.Equal(t, "uri", b.Name())
797
798 type Tag struct {
799 Name string `uri:"name"`
800 }
801 var tag Tag
802 m := make(map[string][]string)
803 m["name"] = []string{"thinkerou"}
804 assert.NoError(t, b.BindUri(m, &tag))
805 assert.Equal(t, "thinkerou", tag.Name)
806
807 type NotSupportStruct struct {
808 Name map[string]any `uri:"name"`
809 }
810 var not NotSupportStruct
811 assert.Error(t, b.BindUri(m, ¬))
812 assert.Equal(t, map[string]any(nil), not.Name)
813 }
814
815 func TestUriInnerBinding(t *testing.T) {
816 type Tag struct {
817 Name string `uri:"name"`
818 S struct {
819 Age int `uri:"age"`
820 }
821 }
822
823 expectedName := "mike"
824 expectedAge := 25
825
826 m := map[string][]string{
827 "name": {expectedName},
828 "age": {strconv.Itoa(expectedAge)},
829 }
830
831 var tag Tag
832 assert.NoError(t, Uri.BindUri(m, &tag))
833 assert.Equal(t, tag.Name, expectedName)
834 assert.Equal(t, tag.S.Age, expectedAge)
835 }
836
837 func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, badBody string) {
838 b := Form
839 assert.Equal(t, "form", b.Name())
840
841 obj := QueryTest{}
842 req := requestWithBody(method, path, body)
843 if method == "POST" {
844 req.Header.Add("Content-Type", MIMEPOSTForm)
845 }
846 err := b.Bind(req, &obj)
847 assert.NoError(t, err)
848 assert.Equal(t, 1, obj.Page)
849 assert.Equal(t, 2, obj.Size)
850 assert.Equal(t, "test-appkey", obj.Appkey)
851 }
852
853 func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) {
854 b := Form
855 assert.Equal(t, "form", b.Name())
856
857 obj := FooBarStruct{}
858 req := requestWithBody(method, path, body)
859 if method == "POST" {
860 req.Header.Add("Content-Type", MIMEPOSTForm)
861 }
862 err := b.Bind(req, &obj)
863 assert.NoError(t, err)
864 assert.Equal(t, "bar", obj.Foo)
865 assert.Equal(t, "foo", obj.Bar)
866
867 obj = FooBarStruct{}
868 req = requestWithBody(method, badPath, badBody)
869 err = JSON.Bind(req, &obj)
870 assert.Error(t, err)
871 }
872
873 func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badBody string) {
874 b := Form
875 assert.Equal(t, "form", b.Name())
876
877 obj := FooDefaultBarStruct{}
878 req := requestWithBody(method, path, body)
879 if method == "POST" {
880 req.Header.Add("Content-Type", MIMEPOSTForm)
881 }
882 err := b.Bind(req, &obj)
883 assert.NoError(t, err)
884 assert.Equal(t, "bar", obj.Foo)
885 assert.Equal(t, "hello", obj.Bar)
886
887 obj = FooDefaultBarStruct{}
888 req = requestWithBody(method, badPath, badBody)
889 err = JSON.Bind(req, &obj)
890 assert.Error(t, err)
891 }
892
893 func TestFormBindingFail(t *testing.T) {
894 b := Form
895 assert.Equal(t, "form", b.Name())
896
897 obj := FooBarStruct{}
898 req, _ := http.NewRequest("POST", "/", nil)
899 err := b.Bind(req, &obj)
900 assert.Error(t, err)
901 }
902
903 func TestFormBindingMultipartFail(t *testing.T) {
904 obj := FooBarStruct{}
905 req, err := http.NewRequest("POST", "/", strings.NewReader("foo=bar"))
906 assert.NoError(t, err)
907 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+";boundary=testboundary")
908 _, err = req.MultipartReader()
909 assert.NoError(t, err)
910 err = Form.Bind(req, &obj)
911 assert.Error(t, err)
912 }
913
914 func TestFormPostBindingFail(t *testing.T) {
915 b := FormPost
916 assert.Equal(t, "form-urlencoded", b.Name())
917
918 obj := FooBarStruct{}
919 req, _ := http.NewRequest("POST", "/", nil)
920 err := b.Bind(req, &obj)
921 assert.Error(t, err)
922 }
923
924 func TestFormMultipartBindingFail(t *testing.T) {
925 b := FormMultipart
926 assert.Equal(t, "multipart/form-data", b.Name())
927
928 obj := FooBarStruct{}
929 req, _ := http.NewRequest("POST", "/", nil)
930 err := b.Bind(req, &obj)
931 assert.Error(t, err)
932 }
933
934 func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody string) {
935 b := Form
936 assert.Equal(t, "form", b.Name())
937
938 obj := FooBarStructForTimeType{}
939 req := requestWithBody(method, path, body)
940 if method == "POST" {
941 req.Header.Add("Content-Type", MIMEPOSTForm)
942 }
943 err := b.Bind(req, &obj)
944
945 assert.NoError(t, err)
946 assert.Equal(t, int64(1510675200), obj.TimeFoo.Unix())
947 assert.Equal(t, "Asia/Chongqing", obj.TimeFoo.Location().String())
948 assert.Equal(t, int64(-62135596800), obj.TimeBar.Unix())
949 assert.Equal(t, "UTC", obj.TimeBar.Location().String())
950 assert.Equal(t, int64(1562400033000000123), obj.CreateTime.UnixNano())
951 assert.Equal(t, int64(1562400033), obj.UnixTime.Unix())
952
953 obj = FooBarStructForTimeType{}
954 req = requestWithBody(method, badPath, badBody)
955 err = JSON.Bind(req, &obj)
956 assert.Error(t, err)
957 }
958
959 func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, body, badBody string) {
960 b := Form
961 assert.Equal(t, "form", b.Name())
962
963 obj := FooStructForTimeTypeNotUnixFormat{}
964 req := requestWithBody(method, path, body)
965 if method == "POST" {
966 req.Header.Add("Content-Type", MIMEPOSTForm)
967 }
968 err := b.Bind(req, &obj)
969 assert.Error(t, err)
970
971 obj = FooStructForTimeTypeNotUnixFormat{}
972 req = requestWithBody(method, badPath, badBody)
973 err = JSON.Bind(req, &obj)
974 assert.Error(t, err)
975 }
976
977 func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) {
978 b := Form
979 assert.Equal(t, "form", b.Name())
980
981 obj := FooStructForTimeTypeNotFormat{}
982 req := requestWithBody(method, path, body)
983 if method == "POST" {
984 req.Header.Add("Content-Type", MIMEPOSTForm)
985 }
986 err := b.Bind(req, &obj)
987 assert.Error(t, err)
988
989 obj = FooStructForTimeTypeNotFormat{}
990 req = requestWithBody(method, badPath, badBody)
991 err = JSON.Bind(req, &obj)
992 assert.Error(t, err)
993 }
994
995 func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body, badBody string) {
996 b := Form
997 assert.Equal(t, "form", b.Name())
998
999 obj := FooStructForTimeTypeFailFormat{}
1000 req := requestWithBody(method, path, body)
1001 if method == "POST" {
1002 req.Header.Add("Content-Type", MIMEPOSTForm)
1003 }
1004 err := b.Bind(req, &obj)
1005 assert.Error(t, err)
1006
1007 obj = FooStructForTimeTypeFailFormat{}
1008 req = requestWithBody(method, badPath, badBody)
1009 err = JSON.Bind(req, &obj)
1010 assert.Error(t, err)
1011 }
1012
1013 func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, body, badBody string) {
1014 b := Form
1015 assert.Equal(t, "form", b.Name())
1016
1017 obj := FooStructForTimeTypeFailLocation{}
1018 req := requestWithBody(method, path, body)
1019 if method == "POST" {
1020 req.Header.Add("Content-Type", MIMEPOSTForm)
1021 }
1022 err := b.Bind(req, &obj)
1023 assert.Error(t, err)
1024
1025 obj = FooStructForTimeTypeFailLocation{}
1026 req = requestWithBody(method, badPath, badBody)
1027 err = JSON.Bind(req, &obj)
1028 assert.Error(t, err)
1029 }
1030
1031 func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBody string) {
1032 b := Form
1033 assert.Equal(t, "form", b.Name())
1034
1035 obj := FooStructForIgnoreFormTag{}
1036 req := requestWithBody(method, path, body)
1037 if method == "POST" {
1038 req.Header.Add("Content-Type", MIMEPOSTForm)
1039 }
1040 err := b.Bind(req, &obj)
1041 assert.NoError(t, err)
1042
1043 assert.Nil(t, obj.Foo)
1044 }
1045
1046 func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBody string) {
1047 b := Form
1048 assert.Equal(t, "form", b.Name())
1049
1050 obj := InvalidNameType{}
1051 req := requestWithBody(method, path, body)
1052 if method == "POST" {
1053 req.Header.Add("Content-Type", MIMEPOSTForm)
1054 }
1055 err := b.Bind(req, &obj)
1056 assert.NoError(t, err)
1057 assert.Equal(t, "", obj.TestName)
1058
1059 obj = InvalidNameType{}
1060 req = requestWithBody(method, badPath, badBody)
1061 err = JSON.Bind(req, &obj)
1062 assert.Error(t, err)
1063 }
1064
1065 func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badBody string) {
1066 b := Form
1067 assert.Equal(t, "form", b.Name())
1068
1069 obj := InvalidNameMapType{}
1070 req := requestWithBody(method, path, body)
1071 if method == "POST" {
1072 req.Header.Add("Content-Type", MIMEPOSTForm)
1073 }
1074 err := b.Bind(req, &obj)
1075 assert.Error(t, err)
1076
1077 obj = InvalidNameMapType{}
1078 req = requestWithBody(method, badPath, badBody)
1079 err = JSON.Bind(req, &obj)
1080 assert.Error(t, err)
1081 }
1082
1083 func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody string, typ string) {
1084 b := Form
1085 assert.Equal(t, "form", b.Name())
1086
1087 req := requestWithBody(method, path, body)
1088 if method == "POST" {
1089 req.Header.Add("Content-Type", MIMEPOSTForm)
1090 }
1091 switch typ {
1092 case "Slice":
1093 obj := FooStructForSliceType{}
1094 err := b.Bind(req, &obj)
1095 assert.NoError(t, err)
1096 assert.Equal(t, []int{1, 2}, obj.SliceFoo)
1097
1098 obj = FooStructForSliceType{}
1099 req = requestWithBody(method, badPath, badBody)
1100 err = JSON.Bind(req, &obj)
1101 assert.Error(t, err)
1102 case "Struct":
1103 obj := FooStructForStructType{}
1104 err := b.Bind(req, &obj)
1105 assert.NoError(t, err)
1106 assert.Equal(t,
1107 struct {
1108 Idx int "form:\"idx\""
1109 }{Idx: 123},
1110 obj.StructFoo)
1111 case "StructPointer":
1112 obj := FooStructForStructPointerType{}
1113 err := b.Bind(req, &obj)
1114 assert.NoError(t, err)
1115 assert.Equal(t,
1116 struct {
1117 Name string "form:\"name\""
1118 }{Name: "thinkerou"},
1119 *obj.StructPointerFoo)
1120 case "Map":
1121 obj := FooStructForMapType{}
1122 err := b.Bind(req, &obj)
1123 assert.NoError(t, err)
1124 assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64))
1125 case "SliceMap":
1126 obj := FooStructForSliceMapType{}
1127 err := b.Bind(req, &obj)
1128 assert.Error(t, err)
1129 case "Ptr":
1130 obj := FooStructForStringPtrType{}
1131 err := b.Bind(req, &obj)
1132 assert.NoError(t, err)
1133 assert.Nil(t, obj.PtrFoo)
1134 assert.Equal(t, "test", *obj.PtrBar)
1135
1136 obj = FooStructForStringPtrType{}
1137 obj.PtrBar = new(string)
1138 err = b.Bind(req, &obj)
1139 assert.NoError(t, err)
1140 assert.Equal(t, "test", *obj.PtrBar)
1141
1142 objErr := FooStructForMapPtrType{}
1143 err = b.Bind(req, &objErr)
1144 assert.Error(t, err)
1145
1146 obj = FooStructForStringPtrType{}
1147 req = requestWithBody(method, badPath, badBody)
1148 err = b.Bind(req, &obj)
1149 assert.Error(t, err)
1150 }
1151 }
1152
1153 func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string) {
1154 b := Query
1155 assert.Equal(t, "query", b.Name())
1156
1157 obj := FooBarStruct{}
1158 req := requestWithBody(method, path, body)
1159 if method == "POST" {
1160 req.Header.Add("Content-Type", MIMEPOSTForm)
1161 }
1162 err := b.Bind(req, &obj)
1163 assert.NoError(t, err)
1164 assert.Equal(t, "bar", obj.Foo)
1165 assert.Equal(t, "foo", obj.Bar)
1166 }
1167
1168 func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody string) {
1169 b := Query
1170 assert.Equal(t, "query", b.Name())
1171
1172 obj := FooStructForMapType{}
1173 req := requestWithBody(method, path, body)
1174 if method == "POST" {
1175 req.Header.Add("Content-Type", MIMEPOSTForm)
1176 }
1177 err := b.Bind(req, &obj)
1178 assert.Error(t, err)
1179 }
1180
1181 func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody string) {
1182 b := Query
1183 assert.Equal(t, "query", b.Name())
1184
1185 obj := FooStructForBoolType{}
1186 req := requestWithBody(method, path, body)
1187 if method == "POST" {
1188 req.Header.Add("Content-Type", MIMEPOSTForm)
1189 }
1190 err := b.Bind(req, &obj)
1191 assert.Error(t, err)
1192 }
1193
1194 func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
1195 assert.Equal(t, name, b.Name())
1196
1197 obj := FooStruct{}
1198 req := requestWithBody("POST", path, body)
1199 err := b.Bind(req, &obj)
1200 assert.NoError(t, err)
1201 assert.Equal(t, "bar", obj.Foo)
1202
1203 obj = FooStruct{}
1204 req = requestWithBody("POST", badPath, badBody)
1205 err = JSON.Bind(req, &obj)
1206 assert.Error(t, err)
1207 }
1208
1209 func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
1210 assert.Equal(t, name, b.Name())
1211
1212 var obj1 []FooStruct
1213 req := requestWithBody("POST", path, body)
1214 err := b.Bind(req, &obj1)
1215 assert.NoError(t, err)
1216
1217 var obj2 []FooStruct
1218 req = requestWithBody("POST", badPath, badBody)
1219 err = JSON.Bind(req, &obj2)
1220 assert.Error(t, err)
1221 }
1222
1223 func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badBody string) {
1224 obj := make(map[string]string)
1225 req := requestWithBody("POST", path, body)
1226 if b.Name() == "form" {
1227 req.Header.Add("Content-Type", MIMEPOSTForm)
1228 }
1229 err := b.Bind(req, &obj)
1230 assert.NoError(t, err)
1231 assert.NotNil(t, obj)
1232 assert.Len(t, obj, 2)
1233 assert.Equal(t, "bar", obj["foo"])
1234 assert.Equal(t, "world", obj["hello"])
1235
1236 if badPath != "" && badBody != "" {
1237 obj = make(map[string]string)
1238 req = requestWithBody("POST", badPath, badBody)
1239 err = b.Bind(req, &obj)
1240 assert.Error(t, err)
1241 }
1242
1243 objInt := make(map[string]int)
1244 req = requestWithBody("POST", path, body)
1245 err = b.Bind(req, &objInt)
1246 assert.Error(t, err)
1247 }
1248
1249 func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
1250 assert.Equal(t, name, b.Name())
1251
1252 obj := FooStructUseNumber{}
1253 req := requestWithBody("POST", path, body)
1254 EnableDecoderUseNumber = true
1255 err := b.Bind(req, &obj)
1256 assert.NoError(t, err)
1257
1258 v, e := obj.Foo.(json.Number).Int64()
1259 assert.NoError(t, e)
1260 assert.Equal(t, int64(123), v)
1261
1262 obj = FooStructUseNumber{}
1263 req = requestWithBody("POST", badPath, badBody)
1264 err = JSON.Bind(req, &obj)
1265 assert.Error(t, err)
1266 }
1267
1268 func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
1269 assert.Equal(t, name, b.Name())
1270
1271 obj := FooStructUseNumber{}
1272 req := requestWithBody("POST", path, body)
1273 EnableDecoderUseNumber = false
1274 err := b.Bind(req, &obj)
1275 assert.NoError(t, err)
1276
1277
1278 assert.Equal(t, float64(123), obj.Foo)
1279
1280 obj = FooStructUseNumber{}
1281 req = requestWithBody("POST", badPath, badBody)
1282 err = JSON.Bind(req, &obj)
1283 assert.Error(t, err)
1284 }
1285
1286 func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath, body, badBody string) {
1287 EnableDecoderDisallowUnknownFields = true
1288 defer func() {
1289 EnableDecoderDisallowUnknownFields = false
1290 }()
1291
1292 obj := FooStructDisallowUnknownFields{}
1293 req := requestWithBody("POST", path, body)
1294 err := b.Bind(req, &obj)
1295 assert.NoError(t, err)
1296 assert.Equal(t, "bar", obj.Foo)
1297
1298 obj = FooStructDisallowUnknownFields{}
1299 req = requestWithBody("POST", badPath, badBody)
1300 err = JSON.Bind(req, &obj)
1301 assert.Error(t, err)
1302 assert.Contains(t, err.Error(), "what")
1303 }
1304
1305 func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
1306 assert.Equal(t, name, b.Name())
1307
1308 obj := FooStruct{}
1309 req := requestWithBody("POST", path, body)
1310 err := b.Bind(req, &obj)
1311 assert.Error(t, err)
1312 assert.Equal(t, "", obj.Foo)
1313
1314 obj = FooStruct{}
1315 req = requestWithBody("POST", badPath, badBody)
1316 err = JSON.Bind(req, &obj)
1317 assert.Error(t, err)
1318 }
1319
1320 func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
1321 assert.Equal(t, name, b.Name())
1322
1323 obj := protoexample.Test{}
1324 req := requestWithBody("POST", path, body)
1325 req.Header.Add("Content-Type", MIMEPROTOBUF)
1326 err := b.Bind(req, &obj)
1327 assert.NoError(t, err)
1328 assert.Equal(t, "yes", *obj.Label)
1329
1330 obj = protoexample.Test{}
1331 req = requestWithBody("POST", badPath, badBody)
1332 req.Header.Add("Content-Type", MIMEPROTOBUF)
1333 err = ProtoBuf.Bind(req, &obj)
1334 assert.Error(t, err)
1335 }
1336
1337 type hook struct{}
1338
1339 func (h hook) Read([]byte) (int, error) {
1340 return 0, errors.New("error")
1341 }
1342
1343 func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
1344 assert.Equal(t, name, b.Name())
1345
1346 obj := protoexample.Test{}
1347 req := requestWithBody("POST", path, body)
1348
1349 req.Body = io.NopCloser(&hook{})
1350 req.Header.Add("Content-Type", MIMEPROTOBUF)
1351 err := b.Bind(req, &obj)
1352 assert.Error(t, err)
1353
1354 invalidobj := FooStruct{}
1355 req.Body = io.NopCloser(strings.NewReader(`{"msg":"hello"}`))
1356 req.Header.Add("Content-Type", MIMEPROTOBUF)
1357 err = b.Bind(req, &invalidobj)
1358 assert.Error(t, err)
1359 assert.Equal(t, err.Error(), "obj is not ProtoMessage")
1360
1361 obj = protoexample.Test{}
1362 req = requestWithBody("POST", badPath, badBody)
1363 req.Header.Add("Content-Type", MIMEPROTOBUF)
1364 err = ProtoBuf.Bind(req, &obj)
1365 assert.Error(t, err)
1366 }
1367
1368 func requestWithBody(method, path, body string) (req *http.Request) {
1369 req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
1370 return
1371 }
1372
View as plain text