2015-04-09 13:15:02 +03:00
|
|
|
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
|
|
|
|
// Use of this source code is governed by a MIT style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package binding
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2015-07-03 05:20:00 +03:00
|
|
|
"mime/multipart"
|
2015-04-09 13:15:02 +03:00
|
|
|
"net/http"
|
|
|
|
"testing"
|
|
|
|
|
2015-10-02 11:42:58 +03:00
|
|
|
"github.com/gin-gonic/gin/binding/example"
|
|
|
|
"github.com/golang/protobuf/proto"
|
2015-04-09 13:15:02 +03:00
|
|
|
"github.com/stretchr/testify/assert"
|
2017-06-12 05:40:15 +03:00
|
|
|
"github.com/ugorji/go/codec"
|
2015-04-09 13:15:02 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
type FooStruct struct {
|
2017-02-23 17:08:37 +03:00
|
|
|
Foo string `msgpack:"foo" json:"foo" form:"foo" xml:"foo" binding:"required"`
|
2015-04-09 13:15:02 +03:00
|
|
|
}
|
|
|
|
|
2015-05-24 04:33:21 +03:00
|
|
|
type FooBarStruct struct {
|
|
|
|
FooStruct
|
2017-02-23 17:08:37 +03:00
|
|
|
Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
|
2015-05-24 04:33:21 +03:00
|
|
|
}
|
|
|
|
|
2015-04-09 13:15:02 +03:00
|
|
|
func TestBindingDefault(t *testing.T) {
|
2015-05-05 16:06:38 +03:00
|
|
|
assert.Equal(t, Default("GET", ""), Form)
|
|
|
|
assert.Equal(t, Default("GET", MIMEJSON), Form)
|
2015-04-09 13:15:02 +03:00
|
|
|
|
|
|
|
assert.Equal(t, Default("POST", MIMEJSON), JSON)
|
|
|
|
assert.Equal(t, Default("PUT", MIMEJSON), JSON)
|
|
|
|
|
|
|
|
assert.Equal(t, Default("POST", MIMEXML), XML)
|
|
|
|
assert.Equal(t, Default("PUT", MIMEXML2), XML)
|
|
|
|
|
2015-05-05 16:06:38 +03:00
|
|
|
assert.Equal(t, Default("POST", MIMEPOSTForm), Form)
|
2015-05-26 17:47:10 +03:00
|
|
|
assert.Equal(t, Default("PUT", MIMEPOSTForm), Form)
|
2015-05-26 15:21:35 +03:00
|
|
|
|
2015-05-26 17:47:10 +03:00
|
|
|
assert.Equal(t, Default("POST", MIMEMultipartPOSTForm), Form)
|
|
|
|
assert.Equal(t, Default("PUT", MIMEMultipartPOSTForm), Form)
|
2015-07-12 12:42:39 +03:00
|
|
|
|
|
|
|
assert.Equal(t, Default("POST", MIMEPROTOBUF), ProtoBuf)
|
|
|
|
assert.Equal(t, Default("PUT", MIMEPROTOBUF), ProtoBuf)
|
2017-02-23 17:08:37 +03:00
|
|
|
|
|
|
|
assert.Equal(t, Default("POST", MIMEMSGPACK), MsgPack)
|
|
|
|
assert.Equal(t, Default("PUT", MIMEMSGPACK2), MsgPack)
|
2015-04-09 13:15:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestBindingJSON(t *testing.T) {
|
2015-05-05 16:06:38 +03:00
|
|
|
testBodyBinding(t,
|
2015-04-09 13:15:02 +03:00
|
|
|
JSON, "json",
|
|
|
|
"/", "/",
|
|
|
|
`{"foo": "bar"}`, `{"bar": "foo"}`)
|
|
|
|
}
|
|
|
|
|
2015-05-05 16:06:38 +03:00
|
|
|
func TestBindingForm(t *testing.T) {
|
|
|
|
testFormBinding(t, "POST",
|
2015-04-09 13:15:02 +03:00
|
|
|
"/", "/",
|
2015-05-24 04:33:21 +03:00
|
|
|
"foo=bar&bar=foo", "bar2=foo")
|
2015-04-09 13:15:02 +03:00
|
|
|
}
|
|
|
|
|
2015-05-05 16:06:38 +03:00
|
|
|
func TestBindingForm2(t *testing.T) {
|
|
|
|
testFormBinding(t, "GET",
|
2015-05-24 04:33:21 +03:00
|
|
|
"/?foo=bar&bar=foo", "/?bar2=foo",
|
2015-04-09 13:15:02 +03:00
|
|
|
"", "")
|
|
|
|
}
|
|
|
|
|
2017-07-19 10:50:05 +03:00
|
|
|
func TestBindingQuery(t *testing.T) {
|
|
|
|
testQueryBinding(t, "POST",
|
|
|
|
"/?foo=bar&bar=foo", "/",
|
|
|
|
"foo=unused", "bar2=foo")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBindingQuery2(t *testing.T) {
|
|
|
|
testQueryBinding(t, "GET",
|
|
|
|
"/?foo=bar&bar=foo", "/?bar2=foo",
|
|
|
|
"foo=unused", "")
|
|
|
|
}
|
|
|
|
|
2015-04-09 13:15:02 +03:00
|
|
|
func TestBindingXML(t *testing.T) {
|
2015-05-05 16:06:38 +03:00
|
|
|
testBodyBinding(t,
|
2015-04-09 13:15:02 +03:00
|
|
|
XML, "xml",
|
|
|
|
"/", "/",
|
|
|
|
"<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>")
|
|
|
|
}
|
|
|
|
|
2015-07-03 05:20:00 +03:00
|
|
|
func createFormPostRequest() *http.Request {
|
|
|
|
req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
|
|
|
|
req.Header.Set("Content-Type", MIMEPOSTForm)
|
|
|
|
return req
|
|
|
|
}
|
|
|
|
|
|
|
|
func createFormMultipartRequest() *http.Request {
|
|
|
|
boundary := "--testboundary"
|
|
|
|
body := new(bytes.Buffer)
|
|
|
|
mw := multipart.NewWriter(body)
|
|
|
|
defer mw.Close()
|
|
|
|
|
|
|
|
mw.SetBoundary(boundary)
|
|
|
|
mw.WriteField("foo", "bar")
|
|
|
|
mw.WriteField("bar", "foo")
|
|
|
|
req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
|
|
|
|
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
|
|
|
|
return req
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBindingFormPost(t *testing.T) {
|
|
|
|
req := createFormPostRequest()
|
|
|
|
var obj FooBarStruct
|
|
|
|
FormPost.Bind(req, &obj)
|
|
|
|
|
|
|
|
assert.Equal(t, obj.Foo, "bar")
|
|
|
|
assert.Equal(t, obj.Bar, "foo")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBindingFormMultipart(t *testing.T) {
|
|
|
|
req := createFormMultipartRequest()
|
|
|
|
var obj FooBarStruct
|
|
|
|
FormMultipart.Bind(req, &obj)
|
|
|
|
|
|
|
|
assert.Equal(t, obj.Foo, "bar")
|
|
|
|
assert.Equal(t, obj.Bar, "foo")
|
|
|
|
}
|
|
|
|
|
2015-07-12 12:42:39 +03:00
|
|
|
func TestBindingProtoBuf(t *testing.T) {
|
|
|
|
test := &example.Test{
|
|
|
|
Label: proto.String("yes"),
|
|
|
|
}
|
|
|
|
data, _ := proto.Marshal(test)
|
|
|
|
|
|
|
|
testProtoBodyBinding(t,
|
|
|
|
ProtoBuf, "protobuf",
|
|
|
|
"/", "/",
|
|
|
|
string(data), string(data[1:]))
|
|
|
|
}
|
|
|
|
|
2017-02-23 17:08:37 +03:00
|
|
|
func TestBindingMsgPack(t *testing.T) {
|
|
|
|
test := FooStruct{
|
|
|
|
Foo: "bar",
|
|
|
|
}
|
|
|
|
|
|
|
|
h := new(codec.MsgpackHandle)
|
|
|
|
assert.NotNil(t, h)
|
|
|
|
buf := bytes.NewBuffer([]byte{})
|
|
|
|
assert.NotNil(t, buf)
|
|
|
|
err := codec.NewEncoder(buf, h).Encode(test)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
data := buf.Bytes()
|
|
|
|
|
|
|
|
testMsgPackBodyBinding(t,
|
|
|
|
MsgPack, "msgpack",
|
|
|
|
"/", "/",
|
|
|
|
string(data), string(data[1:]))
|
|
|
|
}
|
|
|
|
|
2015-05-31 17:18:50 +03:00
|
|
|
func TestValidationFails(t *testing.T) {
|
|
|
|
var obj FooStruct
|
|
|
|
req := requestWithBody("POST", "/", `{"bar": "foo"}`)
|
|
|
|
err := JSON.Bind(req, &obj)
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestValidationDisabled(t *testing.T) {
|
|
|
|
backup := Validator
|
|
|
|
Validator = nil
|
|
|
|
defer func() { Validator = backup }()
|
|
|
|
|
|
|
|
var obj FooStruct
|
|
|
|
req := requestWithBody("POST", "/", `{"bar": "foo"}`)
|
|
|
|
err := JSON.Bind(req, &obj)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2015-12-31 09:49:38 +03:00
|
|
|
func TestExistsSucceeds(t *testing.T) {
|
|
|
|
type HogeStruct struct {
|
|
|
|
Hoge *int `json:"hoge" binding:"exists"`
|
|
|
|
}
|
|
|
|
|
|
|
|
var obj HogeStruct
|
|
|
|
req := requestWithBody("POST", "/", `{"hoge": 0}`)
|
|
|
|
err := JSON.Bind(req, &obj)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExistsFails(t *testing.T) {
|
|
|
|
type HogeStruct struct {
|
|
|
|
Hoge *int `json:"foo" binding:"exists"`
|
|
|
|
}
|
|
|
|
|
|
|
|
var obj HogeStruct
|
|
|
|
req := requestWithBody("POST", "/", `{"boen": 0}`)
|
|
|
|
err := JSON.Bind(req, &obj)
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2015-05-05 16:06:38 +03:00
|
|
|
func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) {
|
|
|
|
b := Form
|
2015-05-26 17:47:10 +03:00
|
|
|
assert.Equal(t, b.Name(), "form")
|
2015-05-05 16:06:38 +03:00
|
|
|
|
2015-05-24 04:33:21 +03:00
|
|
|
obj := FooBarStruct{}
|
2015-05-05 16:06:38 +03:00
|
|
|
req := requestWithBody(method, path, body)
|
|
|
|
if method == "POST" {
|
|
|
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
|
|
|
}
|
|
|
|
err := b.Bind(req, &obj)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, obj.Foo, "bar")
|
2015-05-24 04:33:21 +03:00
|
|
|
assert.Equal(t, obj.Bar, "foo")
|
2015-05-05 16:06:38 +03:00
|
|
|
|
2015-05-24 04:33:21 +03:00
|
|
|
obj = FooBarStruct{}
|
2015-05-05 16:06:38 +03:00
|
|
|
req = requestWithBody(method, badPath, badBody)
|
|
|
|
err = JSON.Bind(req, &obj)
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2017-07-19 10:50:05 +03:00
|
|
|
func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string) {
|
|
|
|
b := Query
|
|
|
|
assert.Equal(t, b.Name(), "query")
|
|
|
|
|
|
|
|
obj := FooBarStruct{}
|
|
|
|
req := requestWithBody(method, path, body)
|
|
|
|
if method == "POST" {
|
|
|
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
|
|
|
}
|
|
|
|
err := b.Bind(req, &obj)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, obj.Foo, "bar")
|
|
|
|
assert.Equal(t, obj.Bar, "foo")
|
|
|
|
}
|
|
|
|
|
2015-05-05 16:06:38 +03:00
|
|
|
func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
2015-04-09 13:15:02 +03:00
|
|
|
assert.Equal(t, b.Name(), name)
|
|
|
|
|
|
|
|
obj := FooStruct{}
|
2015-05-05 16:06:38 +03:00
|
|
|
req := requestWithBody("POST", path, body)
|
2015-04-09 13:15:02 +03:00
|
|
|
err := b.Bind(req, &obj)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, obj.Foo, "bar")
|
|
|
|
|
|
|
|
obj = FooStruct{}
|
2015-05-05 16:06:38 +03:00
|
|
|
req = requestWithBody("POST", badPath, badBody)
|
2015-04-09 13:15:02 +03:00
|
|
|
err = JSON.Bind(req, &obj)
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2015-07-12 12:42:39 +03:00
|
|
|
func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
|
|
|
assert.Equal(t, b.Name(), name)
|
|
|
|
|
|
|
|
obj := example.Test{}
|
|
|
|
req := requestWithBody("POST", path, body)
|
|
|
|
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
|
|
|
err := b.Bind(req, &obj)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, *obj.Label, "yes")
|
|
|
|
|
|
|
|
obj = example.Test{}
|
|
|
|
req = requestWithBody("POST", badPath, badBody)
|
|
|
|
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
|
|
|
err = ProtoBuf.Bind(req, &obj)
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2017-02-23 17:08:37 +03:00
|
|
|
func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
|
|
|
assert.Equal(t, b.Name(), name)
|
|
|
|
|
|
|
|
obj := FooStruct{}
|
|
|
|
req := requestWithBody("POST", path, body)
|
|
|
|
req.Header.Add("Content-Type", MIMEMSGPACK)
|
|
|
|
err := b.Bind(req, &obj)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, obj.Foo, "bar")
|
|
|
|
|
|
|
|
obj = FooStruct{}
|
|
|
|
req = requestWithBody("POST", badPath, badBody)
|
|
|
|
req.Header.Add("Content-Type", MIMEMSGPACK)
|
|
|
|
err = MsgPack.Bind(req, &obj)
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2015-05-05 16:06:38 +03:00
|
|
|
func requestWithBody(method, path, body string) (req *http.Request) {
|
|
|
|
req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
|
2015-04-09 13:15:02 +03:00
|
|
|
return
|
|
|
|
}
|