Merge tag 'tags/v1.11.0'
This commit is contained in:
@@ -8,6 +8,7 @@ package binding
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -39,20 +40,20 @@ func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body,
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
obj := FooStruct{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
req.Header.Add("Content-Type", MIMEMSGPACK)
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "bar", obj.Foo)
|
||||
|
||||
obj = FooStruct{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
req.Header.Add("Content-Type", MIMEMSGPACK)
|
||||
err = MsgPack.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestBindingDefaultMsgPack(t *testing.T) {
|
||||
assert.Equal(t, MsgPack, Default("POST", MIMEMSGPACK))
|
||||
assert.Equal(t, MsgPack, Default("PUT", MIMEMSGPACK2))
|
||||
assert.Equal(t, MsgPack, Default(http.MethodPost, MIMEMSGPACK))
|
||||
assert.Equal(t, MsgPack, Default(http.MethodPut, MIMEMSGPACK2))
|
||||
}
|
||||
|
||||
+134
-130
@@ -51,8 +51,6 @@ type FooBarFileStruct struct {
|
||||
type FooBarFileFailStruct struct {
|
||||
FooBarStruct
|
||||
File *multipart.FileHeader `invalid_name:"file" binding:"required"`
|
||||
// for unexport test
|
||||
data *multipart.FileHeader `form:"data" binding:"required"`
|
||||
}
|
||||
|
||||
type FooDefaultBarStruct struct {
|
||||
@@ -69,15 +67,19 @@ type FooStructDisallowUnknownFields struct {
|
||||
}
|
||||
|
||||
type FooBarStructForTimeType struct {
|
||||
TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
|
||||
TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
|
||||
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
|
||||
UnixTime time.Time `form:"unixTime" time_format:"unix"`
|
||||
TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
|
||||
TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
|
||||
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
|
||||
UnixTime time.Time `form:"unixTime" time_format:"unix"`
|
||||
UnixMilliTime time.Time `form:"unixMilliTime" time_format:"unixmilli"`
|
||||
UnixMicroTime time.Time `form:"unixMicroTime" time_format:"uNiXmiCrO"`
|
||||
}
|
||||
|
||||
type FooStructForTimeTypeNotUnixFormat struct {
|
||||
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
|
||||
UnixTime time.Time `form:"unixTime" time_format:"unix"`
|
||||
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
|
||||
UnixTime time.Time `form:"unixTime" time_format:"unix"`
|
||||
UnixMilliTime time.Time `form:"unixMilliTime" time_format:"unixMilli"`
|
||||
UnixMicroTime time.Time `form:"unixMicroTime" time_format:"unixMicro"`
|
||||
}
|
||||
|
||||
type FooStructForTimeTypeNotFormat struct {
|
||||
@@ -145,31 +147,31 @@ type FooStructForMapPtrType struct {
|
||||
}
|
||||
|
||||
func TestBindingDefault(t *testing.T) {
|
||||
assert.Equal(t, Form, Default("GET", ""))
|
||||
assert.Equal(t, Form, Default("GET", MIMEJSON))
|
||||
assert.Equal(t, Form, Default(http.MethodGet, ""))
|
||||
assert.Equal(t, Form, Default(http.MethodGet, MIMEJSON))
|
||||
|
||||
assert.Equal(t, JSON, Default("POST", MIMEJSON))
|
||||
assert.Equal(t, JSON, Default("PUT", MIMEJSON))
|
||||
assert.Equal(t, JSON, Default(http.MethodPost, MIMEJSON))
|
||||
assert.Equal(t, JSON, Default(http.MethodPut, MIMEJSON))
|
||||
|
||||
assert.Equal(t, XML, Default("POST", MIMEXML))
|
||||
assert.Equal(t, XML, Default("PUT", MIMEXML2))
|
||||
assert.Equal(t, XML, Default(http.MethodPost, MIMEXML))
|
||||
assert.Equal(t, XML, Default(http.MethodPut, MIMEXML2))
|
||||
|
||||
assert.Equal(t, Form, Default("POST", MIMEPOSTForm))
|
||||
assert.Equal(t, Form, Default("PUT", MIMEPOSTForm))
|
||||
assert.Equal(t, Form, Default(http.MethodPost, MIMEPOSTForm))
|
||||
assert.Equal(t, Form, Default(http.MethodPut, MIMEPOSTForm))
|
||||
|
||||
assert.Equal(t, FormMultipart, Default("POST", MIMEMultipartPOSTForm))
|
||||
assert.Equal(t, FormMultipart, Default("PUT", MIMEMultipartPOSTForm))
|
||||
assert.Equal(t, FormMultipart, Default(http.MethodPost, MIMEMultipartPOSTForm))
|
||||
assert.Equal(t, FormMultipart, Default(http.MethodPut, MIMEMultipartPOSTForm))
|
||||
|
||||
assert.Equal(t, ProtoBuf, Default("POST", MIMEPROTOBUF))
|
||||
assert.Equal(t, ProtoBuf, Default("PUT", MIMEPROTOBUF))
|
||||
assert.Equal(t, ProtoBuf, Default(http.MethodPost, MIMEPROTOBUF))
|
||||
assert.Equal(t, ProtoBuf, Default(http.MethodPut, MIMEPROTOBUF))
|
||||
|
||||
assert.Equal(t, YAML, Default("POST", MIMEYAML))
|
||||
assert.Equal(t, YAML, Default("PUT", MIMEYAML))
|
||||
assert.Equal(t, YAML, Default("POST", MIMEYAML2))
|
||||
assert.Equal(t, YAML, Default("PUT", MIMEYAML2))
|
||||
assert.Equal(t, YAML, Default(http.MethodPost, MIMEYAML))
|
||||
assert.Equal(t, YAML, Default(http.MethodPut, MIMEYAML))
|
||||
assert.Equal(t, YAML, Default(http.MethodPost, MIMEYAML2))
|
||||
assert.Equal(t, YAML, Default(http.MethodPut, MIMEYAML2))
|
||||
|
||||
assert.Equal(t, TOML, Default("POST", MIMETOML))
|
||||
assert.Equal(t, TOML, Default("PUT", MIMETOML))
|
||||
assert.Equal(t, TOML, Default(http.MethodPost, MIMETOML))
|
||||
assert.Equal(t, TOML, Default(http.MethodPut, MIMETOML))
|
||||
}
|
||||
|
||||
func TestBindingJSONNilBody(t *testing.T) {
|
||||
@@ -227,137 +229,137 @@ func TestBindingJSONStringMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBindingForm(t *testing.T) {
|
||||
testFormBinding(t, "POST",
|
||||
testFormBinding(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"foo=bar&bar=foo", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingForm2(t *testing.T) {
|
||||
testFormBinding(t, "GET",
|
||||
testFormBinding(t, http.MethodGet,
|
||||
"/?foo=bar&bar=foo", "/?bar2=foo",
|
||||
"", "")
|
||||
}
|
||||
|
||||
func TestBindingFormEmbeddedStruct(t *testing.T) {
|
||||
testFormBindingEmbeddedStruct(t, "POST",
|
||||
testFormBindingEmbeddedStruct(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"page=1&size=2&appkey=test-appkey", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingFormEmbeddedStruct2(t *testing.T) {
|
||||
testFormBindingEmbeddedStruct(t, "GET",
|
||||
testFormBindingEmbeddedStruct(t, http.MethodGet,
|
||||
"/?page=1&size=2&appkey=test-appkey", "/?bar2=foo",
|
||||
"", "")
|
||||
}
|
||||
|
||||
func TestBindingFormDefaultValue(t *testing.T) {
|
||||
testFormBindingDefaultValue(t, "POST",
|
||||
testFormBindingDefaultValue(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"foo=bar", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingFormDefaultValue2(t *testing.T) {
|
||||
testFormBindingDefaultValue(t, "GET",
|
||||
testFormBindingDefaultValue(t, http.MethodGet,
|
||||
"/?foo=bar", "/?bar2=foo",
|
||||
"", "")
|
||||
}
|
||||
|
||||
func TestBindingFormForTime(t *testing.T) {
|
||||
testFormBindingForTime(t, "POST",
|
||||
testFormBindingForTime(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "bar2=foo")
|
||||
testFormBindingForTimeNotUnixFormat(t, "POST",
|
||||
"time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033&unixMilliTime=1562400033001&unixMicroTime=1562400033000012", "bar2=foo")
|
||||
testFormBindingForTimeNotUnixFormat(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
|
||||
testFormBindingForTimeNotFormat(t, "POST",
|
||||
"time_foo=2017-11-15&createTime=bad&unixTime=bad&unixMilliTime=bad&unixMicroTime=bad", "bar2=foo")
|
||||
testFormBindingForTimeNotFormat(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"time_foo=2017-11-15", "bar2=foo")
|
||||
testFormBindingForTimeFailFormat(t, "POST",
|
||||
testFormBindingForTimeFailFormat(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"time_foo=2017-11-15", "bar2=foo")
|
||||
testFormBindingForTimeFailLocation(t, "POST",
|
||||
testFormBindingForTimeFailLocation(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"time_foo=2017-11-15", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingFormForTime2(t *testing.T) {
|
||||
testFormBindingForTime(t, "GET",
|
||||
"/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "/?bar2=foo",
|
||||
testFormBindingForTime(t, http.MethodGet,
|
||||
"/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033&unixMilliTime=1562400033001&unixMicroTime=1562400033000012", "/?bar2=foo",
|
||||
"", "")
|
||||
testFormBindingForTimeNotUnixFormat(t, "POST",
|
||||
testFormBindingForTimeNotUnixFormat(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
|
||||
testFormBindingForTimeNotFormat(t, "GET",
|
||||
"time_foo=2017-11-15&createTime=bad&unixTime=bad&unixMilliTime=bad&unixMicroTime=bad", "bar2=foo")
|
||||
testFormBindingForTimeNotFormat(t, http.MethodGet,
|
||||
"/?time_foo=2017-11-15", "/?bar2=foo",
|
||||
"", "")
|
||||
testFormBindingForTimeFailFormat(t, "GET",
|
||||
testFormBindingForTimeFailFormat(t, http.MethodGet,
|
||||
"/?time_foo=2017-11-15", "/?bar2=foo",
|
||||
"", "")
|
||||
testFormBindingForTimeFailLocation(t, "GET",
|
||||
testFormBindingForTimeFailLocation(t, http.MethodGet,
|
||||
"/?time_foo=2017-11-15", "/?bar2=foo",
|
||||
"", "")
|
||||
}
|
||||
|
||||
func TestFormBindingIgnoreField(t *testing.T) {
|
||||
testFormBindingIgnoreField(t, "POST",
|
||||
testFormBindingIgnoreField(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"-=bar", "")
|
||||
}
|
||||
|
||||
func TestBindingFormInvalidName(t *testing.T) {
|
||||
testFormBindingInvalidName(t, "POST",
|
||||
testFormBindingInvalidName(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"test_name=bar", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingFormInvalidName2(t *testing.T) {
|
||||
testFormBindingInvalidName2(t, "POST",
|
||||
testFormBindingInvalidName2(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"map_foo=bar", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingFormForType(t *testing.T) {
|
||||
testFormBindingForType(t, "POST",
|
||||
testFormBindingForType(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"map_foo={\"bar\":123}", "map_foo=1", "Map")
|
||||
|
||||
testFormBindingForType(t, "POST",
|
||||
testFormBindingForType(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"slice_foo=1&slice_foo=2", "bar2=1&bar2=2", "Slice")
|
||||
|
||||
testFormBindingForType(t, "GET",
|
||||
testFormBindingForType(t, http.MethodGet,
|
||||
"/?slice_foo=1&slice_foo=2", "/?bar2=1&bar2=2",
|
||||
"", "", "Slice")
|
||||
|
||||
testFormBindingForType(t, "POST",
|
||||
testFormBindingForType(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"slice_map_foo=1&slice_map_foo=2", "bar2=1&bar2=2", "SliceMap")
|
||||
|
||||
testFormBindingForType(t, "GET",
|
||||
testFormBindingForType(t, http.MethodGet,
|
||||
"/?slice_map_foo=1&slice_map_foo=2", "/?bar2=1&bar2=2",
|
||||
"", "", "SliceMap")
|
||||
|
||||
testFormBindingForType(t, "POST",
|
||||
testFormBindingForType(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"ptr_bar=test", "bar2=test", "Ptr")
|
||||
|
||||
testFormBindingForType(t, "GET",
|
||||
testFormBindingForType(t, http.MethodGet,
|
||||
"/?ptr_bar=test", "/?bar2=test",
|
||||
"", "", "Ptr")
|
||||
|
||||
testFormBindingForType(t, "POST",
|
||||
testFormBindingForType(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"idx=123", "id1=1", "Struct")
|
||||
|
||||
testFormBindingForType(t, "GET",
|
||||
testFormBindingForType(t, http.MethodGet,
|
||||
"/?idx=123", "/?id1=1",
|
||||
"", "", "Struct")
|
||||
|
||||
testFormBindingForType(t, "POST",
|
||||
testFormBindingForType(t, http.MethodPost,
|
||||
"/", "/",
|
||||
"name=thinkerou", "name1=ou", "StructPointer")
|
||||
|
||||
testFormBindingForType(t, "GET",
|
||||
testFormBindingForType(t, http.MethodGet,
|
||||
"/?name=thinkerou", "/?name1=ou",
|
||||
"", "", "StructPointer")
|
||||
}
|
||||
@@ -374,7 +376,7 @@ func TestBindingFormStringMap(t *testing.T) {
|
||||
|
||||
func TestBindingFormStringSliceMap(t *testing.T) {
|
||||
obj := make(map[string][]string)
|
||||
req := requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
|
||||
req := requestWithBody(http.MethodPost, "/", "foo=something&foo=bar&hello=world")
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
err := Form.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
@@ -387,38 +389,38 @@ func TestBindingFormStringSliceMap(t *testing.T) {
|
||||
assert.True(t, reflect.DeepEqual(obj, target))
|
||||
|
||||
objInvalid := make(map[string][]int)
|
||||
req = requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
|
||||
req = requestWithBody(http.MethodPost, "/", "foo=something&foo=bar&hello=world")
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
err = Form.Bind(req, &objInvalid)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestBindingQuery(t *testing.T) {
|
||||
testQueryBinding(t, "POST",
|
||||
testQueryBinding(t, http.MethodPost,
|
||||
"/?foo=bar&bar=foo", "/",
|
||||
"foo=unused", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingQuery2(t *testing.T) {
|
||||
testQueryBinding(t, "GET",
|
||||
testQueryBinding(t, http.MethodGet,
|
||||
"/?foo=bar&bar=foo", "/?bar2=foo",
|
||||
"foo=unused", "")
|
||||
}
|
||||
|
||||
func TestBindingQueryFail(t *testing.T) {
|
||||
testQueryBindingFail(t, "POST",
|
||||
testQueryBindingFail(t, http.MethodPost,
|
||||
"/?map_foo=", "/",
|
||||
"map_foo=unused", "bar2=foo")
|
||||
}
|
||||
|
||||
func TestBindingQueryFail2(t *testing.T) {
|
||||
testQueryBindingFail(t, "GET",
|
||||
testQueryBindingFail(t, http.MethodGet,
|
||||
"/?map_foo=", "/?bar2=foo",
|
||||
"map_foo=unused", "")
|
||||
}
|
||||
|
||||
func TestBindingQueryBoolFail(t *testing.T) {
|
||||
testQueryBindingBoolFail(t, "GET",
|
||||
testQueryBindingBoolFail(t, http.MethodGet,
|
||||
"/?bool_foo=fasl", "/?bar2=foo",
|
||||
"bool_foo=unused", "")
|
||||
}
|
||||
@@ -427,7 +429,7 @@ func TestBindingQueryStringMap(t *testing.T) {
|
||||
b := Query
|
||||
|
||||
obj := make(map[string]string)
|
||||
req := requestWithBody("GET", "/?foo=bar&hello=world", "")
|
||||
req := requestWithBody(http.MethodGet, "/?foo=bar&hello=world", "")
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, obj)
|
||||
@@ -436,7 +438,7 @@ func TestBindingQueryStringMap(t *testing.T) {
|
||||
assert.Equal(t, "world", obj["hello"])
|
||||
|
||||
obj = make(map[string]string)
|
||||
req = requestWithBody("GET", "/?foo=bar&foo=2&hello=world", "") // should pick last
|
||||
req = requestWithBody(http.MethodGet, "/?foo=bar&foo=2&hello=world", "") // should pick last
|
||||
err = b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, obj)
|
||||
@@ -495,28 +497,28 @@ func TestBindingYAMLFail(t *testing.T) {
|
||||
}
|
||||
|
||||
func createFormPostRequest(t *testing.T) *http.Request {
|
||||
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
|
||||
req, err := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEPOSTForm)
|
||||
return req
|
||||
}
|
||||
|
||||
func createDefaultFormPostRequest(t *testing.T) *http.Request {
|
||||
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
|
||||
req, err := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEPOSTForm)
|
||||
return req
|
||||
}
|
||||
|
||||
func createFormPostRequestForMap(t *testing.T) *http.Request {
|
||||
req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}"))
|
||||
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}"))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEPOSTForm)
|
||||
return req
|
||||
}
|
||||
|
||||
func createFormPostRequestForMapFail(t *testing.T) *http.Request {
|
||||
req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello"))
|
||||
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello"))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEPOSTForm)
|
||||
return req
|
||||
@@ -540,7 +542,7 @@ func createFormFilesMultipartRequest(t *testing.T) *http.Request {
|
||||
_, err = io.Copy(fw, f)
|
||||
require.NoError(t, err)
|
||||
|
||||
req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
|
||||
req, err2 := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", body)
|
||||
require.NoError(t, err2)
|
||||
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
|
||||
|
||||
@@ -565,7 +567,7 @@ func createFormFilesMultipartRequestFail(t *testing.T) *http.Request {
|
||||
_, err = io.Copy(fw, f)
|
||||
require.NoError(t, err)
|
||||
|
||||
req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
|
||||
req, err2 := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", body)
|
||||
require.NoError(t, err2)
|
||||
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
|
||||
|
||||
@@ -581,7 +583,7 @@ func createFormMultipartRequest(t *testing.T) *http.Request {
|
||||
require.NoError(t, mw.SetBoundary(boundary))
|
||||
require.NoError(t, mw.WriteField("foo", "bar"))
|
||||
require.NoError(t, mw.WriteField("bar", "foo"))
|
||||
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
|
||||
req, err := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", body)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
|
||||
return req
|
||||
@@ -595,7 +597,7 @@ func createFormMultipartRequestForMap(t *testing.T) *http.Request {
|
||||
|
||||
require.NoError(t, mw.SetBoundary(boundary))
|
||||
require.NoError(t, mw.WriteField("map_foo", "{\"bar\":123, \"name\":\"thinkerou\", \"pai\": 3.14}"))
|
||||
req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
|
||||
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", body)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
|
||||
return req
|
||||
@@ -609,7 +611,7 @@ func createFormMultipartRequestForMapFail(t *testing.T) *http.Request {
|
||||
|
||||
require.NoError(t, mw.SetBoundary(boundary))
|
||||
require.NoError(t, mw.WriteField("map_foo", "3.14"))
|
||||
req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
|
||||
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", body)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
|
||||
return req
|
||||
@@ -731,7 +733,7 @@ func TestBindingProtoBufFail(t *testing.T) {
|
||||
|
||||
func TestValidationFails(t *testing.T) {
|
||||
var obj FooStruct
|
||||
req := requestWithBody("POST", "/", `{"bar": "foo"}`)
|
||||
req := requestWithBody(http.MethodPost, "/", `{"bar": "foo"}`)
|
||||
err := JSON.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -742,7 +744,7 @@ func TestValidationDisabled(t *testing.T) {
|
||||
defer func() { Validator = backup }()
|
||||
|
||||
var obj FooStruct
|
||||
req := requestWithBody("POST", "/", `{"bar": "foo"}`)
|
||||
req := requestWithBody(http.MethodPost, "/", `{"bar": "foo"}`)
|
||||
err := JSON.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -753,7 +755,7 @@ func TestRequiredSucceeds(t *testing.T) {
|
||||
}
|
||||
|
||||
var obj HogeStruct
|
||||
req := requestWithBody("POST", "/", `{"hoge": 0}`)
|
||||
req := requestWithBody(http.MethodPost, "/", `{"hoge": 0}`)
|
||||
err := JSON.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -764,7 +766,7 @@ func TestRequiredFails(t *testing.T) {
|
||||
}
|
||||
|
||||
var obj HogeStruct
|
||||
req := requestWithBody("POST", "/", `{"boen": 0}`)
|
||||
req := requestWithBody(http.MethodPost, "/", `{"boen": 0}`)
|
||||
err := JSON.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -778,12 +780,12 @@ func TestHeaderBinding(t *testing.T) {
|
||||
}
|
||||
|
||||
var theader tHeader
|
||||
req := requestWithBody("GET", "/", "")
|
||||
req := requestWithBody(http.MethodGet, "/", "")
|
||||
req.Header.Add("limit", "1000")
|
||||
require.NoError(t, h.Bind(req, &theader))
|
||||
assert.Equal(t, 1000, theader.Limit)
|
||||
|
||||
req = requestWithBody("GET", "/", "")
|
||||
req = requestWithBody(http.MethodGet, "/", "")
|
||||
req.Header.Add("fail", `{fail:fail}`)
|
||||
|
||||
type failStruct struct {
|
||||
@@ -843,7 +845,7 @@ func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, ba
|
||||
|
||||
obj := QueryTest{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -859,7 +861,7 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
|
||||
|
||||
obj := FooBarStruct{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -879,7 +881,7 @@ func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badB
|
||||
|
||||
obj := FooDefaultBarStruct{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -898,14 +900,14 @@ func TestFormBindingFail(t *testing.T) {
|
||||
assert.Equal(t, "form", b.Name())
|
||||
|
||||
obj := FooBarStruct{}
|
||||
req, _ := http.NewRequest("POST", "/", nil)
|
||||
req, _ := http.NewRequest(http.MethodPost, "/", nil)
|
||||
err := b.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestFormBindingMultipartFail(t *testing.T) {
|
||||
obj := FooBarStruct{}
|
||||
req, err := http.NewRequest("POST", "/", strings.NewReader("foo=bar"))
|
||||
req, err := http.NewRequest(http.MethodPost, "/", strings.NewReader("foo=bar"))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+";boundary=testboundary")
|
||||
_, err = req.MultipartReader()
|
||||
@@ -919,7 +921,7 @@ func TestFormPostBindingFail(t *testing.T) {
|
||||
assert.Equal(t, "form-urlencoded", b.Name())
|
||||
|
||||
obj := FooBarStruct{}
|
||||
req, _ := http.NewRequest("POST", "/", nil)
|
||||
req, _ := http.NewRequest(http.MethodPost, "/", nil)
|
||||
err := b.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -929,7 +931,7 @@ func TestFormMultipartBindingFail(t *testing.T) {
|
||||
assert.Equal(t, "multipart/form-data", b.Name())
|
||||
|
||||
obj := FooBarStruct{}
|
||||
req, _ := http.NewRequest("POST", "/", nil)
|
||||
req, _ := http.NewRequest(http.MethodPost, "/", nil)
|
||||
err := b.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -940,7 +942,7 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
|
||||
|
||||
obj := FooBarStructForTimeType{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -952,6 +954,8 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
|
||||
assert.Equal(t, "UTC", obj.TimeBar.Location().String())
|
||||
assert.Equal(t, int64(1562400033000000123), obj.CreateTime.UnixNano())
|
||||
assert.Equal(t, int64(1562400033), obj.UnixTime.Unix())
|
||||
assert.Equal(t, int64(1562400033001), obj.UnixMilliTime.UnixMilli())
|
||||
assert.Equal(t, int64(1562400033000012), obj.UnixMicroTime.UnixMicro())
|
||||
|
||||
obj = FooBarStructForTimeType{}
|
||||
req = requestWithBody(method, badPath, badBody)
|
||||
@@ -965,7 +969,7 @@ func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, bo
|
||||
|
||||
obj := FooStructForTimeTypeNotUnixFormat{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -983,7 +987,7 @@ func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body,
|
||||
|
||||
obj := FooStructForTimeTypeNotFormat{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1001,7 +1005,7 @@ func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body,
|
||||
|
||||
obj := FooStructForTimeTypeFailFormat{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1019,7 +1023,7 @@ func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, bod
|
||||
|
||||
obj := FooStructForTimeTypeFailLocation{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1037,7 +1041,7 @@ func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBo
|
||||
|
||||
obj := FooStructForIgnoreFormTag{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1052,12 +1056,12 @@ func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBo
|
||||
|
||||
obj := InvalidNameType{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "", obj.TestName)
|
||||
assert.Empty(t, obj.TestName)
|
||||
|
||||
obj = InvalidNameType{}
|
||||
req = requestWithBody(method, badPath, badBody)
|
||||
@@ -1071,7 +1075,7 @@ func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badB
|
||||
|
||||
obj := InvalidNameMapType{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1088,7 +1092,7 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s
|
||||
assert.Equal(t, "form", b.Name())
|
||||
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
switch typ {
|
||||
@@ -1159,7 +1163,7 @@ func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string)
|
||||
|
||||
obj := FooBarStruct{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1174,7 +1178,7 @@ func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody str
|
||||
|
||||
obj := FooStructForMapType{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1187,7 +1191,7 @@ func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody
|
||||
|
||||
obj := FooStructForBoolType{}
|
||||
req := requestWithBody(method, path, body)
|
||||
if method == "POST" {
|
||||
if method == http.MethodPost {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
err := b.Bind(req, &obj)
|
||||
@@ -1198,13 +1202,13 @@ func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
obj := FooStruct{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "bar", obj.Foo)
|
||||
|
||||
obj = FooStruct{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
err = JSON.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -1213,19 +1217,19 @@ func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, ba
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
var obj1 []FooStruct
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
err := b.Bind(req, &obj1)
|
||||
require.NoError(t, err)
|
||||
|
||||
var obj2 []FooStruct
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
err = JSON.Bind(req, &obj2)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badBody string) {
|
||||
obj := make(map[string]string)
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
if b.Name() == "form" {
|
||||
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||
}
|
||||
@@ -1238,13 +1242,13 @@ func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badB
|
||||
|
||||
if badPath != "" && badBody != "" {
|
||||
obj = make(map[string]string)
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
err = b.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
objInt := make(map[string]int)
|
||||
req = requestWithBody("POST", path, body)
|
||||
req = requestWithBody(http.MethodPost, path, body)
|
||||
err = b.Bind(req, &objInt)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -1253,7 +1257,7 @@ func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
obj := FooStructUseNumber{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
EnableDecoderUseNumber = true
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
@@ -1263,7 +1267,7 @@ func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body
|
||||
assert.Equal(t, int64(123), v)
|
||||
|
||||
obj = FooStructUseNumber{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
err = JSON.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -1272,7 +1276,7 @@ func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, bod
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
obj := FooStructUseNumber{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
EnableDecoderUseNumber = false
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
@@ -1281,7 +1285,7 @@ func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, bod
|
||||
assert.InDelta(t, float64(123), obj.Foo, 0.01)
|
||||
|
||||
obj = FooStructUseNumber{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
err = JSON.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -1293,13 +1297,13 @@ func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath
|
||||
}()
|
||||
|
||||
obj := FooStructDisallowUnknownFields{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "bar", obj.Foo)
|
||||
|
||||
obj = FooStructDisallowUnknownFields{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
err = JSON.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "what")
|
||||
@@ -1309,13 +1313,13 @@ func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, bad
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
obj := FooStruct{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
err := b.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, "", obj.Foo)
|
||||
assert.Empty(t, obj.Foo)
|
||||
|
||||
obj = FooStruct{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
err = JSON.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -1324,14 +1328,14 @@ func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, ba
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
obj := protoexample.Test{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
||||
err := b.Bind(req, &obj)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "yes", *obj.Label)
|
||||
|
||||
obj = protoexample.Test{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
||||
err = ProtoBuf.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
@@ -1358,28 +1362,28 @@ func TestPlainBinding(t *testing.T) {
|
||||
assert.Equal(t, "plain", p.Name())
|
||||
|
||||
var s string
|
||||
req := requestWithBody("POST", "/", "test string")
|
||||
req := requestWithBody(http.MethodPost, "/", "test string")
|
||||
require.NoError(t, p.Bind(req, &s))
|
||||
assert.Equal(t, "test string", s)
|
||||
|
||||
var bs []byte
|
||||
req = requestWithBody("POST", "/", "test []byte")
|
||||
req = requestWithBody(http.MethodPost, "/", "test []byte")
|
||||
require.NoError(t, p.Bind(req, &bs))
|
||||
assert.Equal(t, bs, []byte("test []byte"))
|
||||
|
||||
var i int
|
||||
req = requestWithBody("POST", "/", "test fail")
|
||||
req = requestWithBody(http.MethodPost, "/", "test fail")
|
||||
require.Error(t, p.Bind(req, &i))
|
||||
|
||||
req = requestWithBody("POST", "/", "")
|
||||
req = requestWithBody(http.MethodPost, "/", "")
|
||||
req.Body = &failRead{}
|
||||
require.Error(t, p.Bind(req, &s))
|
||||
|
||||
req = requestWithBody("POST", "/", "")
|
||||
req = requestWithBody(http.MethodPost, "/", "")
|
||||
require.NoError(t, p.Bind(req, nil))
|
||||
|
||||
var ptr *string
|
||||
req = requestWithBody("POST", "/", "")
|
||||
req = requestWithBody(http.MethodPost, "/", "")
|
||||
require.NoError(t, p.Bind(req, ptr))
|
||||
}
|
||||
|
||||
@@ -1387,7 +1391,7 @@ func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body
|
||||
assert.Equal(t, name, b.Name())
|
||||
|
||||
obj := protoexample.Test{}
|
||||
req := requestWithBody("POST", path, body)
|
||||
req := requestWithBody(http.MethodPost, path, body)
|
||||
|
||||
req.Body = io.NopCloser(&hook{})
|
||||
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
||||
@@ -1402,7 +1406,7 @@ func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body
|
||||
assert.Equal(t, "obj is not ProtoMessage", err.Error())
|
||||
|
||||
obj = protoexample.Test{}
|
||||
req = requestWithBody("POST", badPath, badBody)
|
||||
req = requestWithBody(http.MethodPost, badPath, badBody)
|
||||
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
||||
err = ProtoBuf.Bind(req, &obj)
|
||||
require.Error(t, err)
|
||||
|
||||
@@ -18,14 +18,16 @@ func TestSliceValidationError(t *testing.T) {
|
||||
{"has nil elements", SliceValidationError{errors.New("test error"), nil}, "[0]: test error"},
|
||||
{"has zero elements", SliceValidationError{}, ""},
|
||||
{"has one element", SliceValidationError{errors.New("test one error")}, "[0]: test one error"},
|
||||
{"has two elements",
|
||||
{
|
||||
"has two elements",
|
||||
SliceValidationError{
|
||||
errors.New("first error"),
|
||||
errors.New("second error"),
|
||||
},
|
||||
"[0]: first error\n[1]: second error",
|
||||
},
|
||||
{"has many elements",
|
||||
{
|
||||
"has many elements",
|
||||
SliceValidationError{
|
||||
errors.New("first error"),
|
||||
errors.New("second error"),
|
||||
|
||||
+5
-3
@@ -11,9 +11,11 @@ import (
|
||||
|
||||
const defaultMemory = 32 << 20
|
||||
|
||||
type formBinding struct{}
|
||||
type formPostBinding struct{}
|
||||
type formMultipartBinding struct{}
|
||||
type (
|
||||
formBinding struct{}
|
||||
formPostBinding struct{}
|
||||
formMultipartBinding struct{}
|
||||
)
|
||||
|
||||
func (formBinding) Name() string {
|
||||
return "form"
|
||||
|
||||
+15
-9
@@ -13,8 +13,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.company.lan/gopkg/gin/codec/json"
|
||||
"git.company.lan/gopkg/gin/internal/bytesconv"
|
||||
"git.company.lan/gopkg/gin/internal/json"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -175,7 +175,7 @@ func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter
|
||||
|
||||
// BindUnmarshaler is the interface used to wrap the UnmarshalParam method.
|
||||
type BindUnmarshaler interface {
|
||||
// UnmarshalParam decodes and assigns a value from an form or query param.
|
||||
// UnmarshalParam decodes and assigns a value from a form or query param.
|
||||
UnmarshalParam(param string) error
|
||||
}
|
||||
|
||||
@@ -333,9 +333,9 @@ func setWithProperType(val string, value reflect.Value, field reflect.StructFiel
|
||||
case multipart.FileHeader:
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface())
|
||||
return json.API.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface())
|
||||
case reflect.Map:
|
||||
return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface())
|
||||
return json.API.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface())
|
||||
case reflect.Ptr:
|
||||
if !value.Elem().IsValid() {
|
||||
value.Set(reflect.New(value.Type().Elem()))
|
||||
@@ -398,18 +398,24 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val
|
||||
}
|
||||
|
||||
switch tf := strings.ToLower(timeFormat); tf {
|
||||
case "unix", "unixnano":
|
||||
case "unix", "unixmilli", "unixmicro", "unixnano":
|
||||
tv, err := strconv.ParseInt(val, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d := time.Duration(1)
|
||||
if tf == "unixnano" {
|
||||
d = time.Second
|
||||
var t time.Time
|
||||
switch tf {
|
||||
case "unix":
|
||||
t = time.Unix(tv, 0)
|
||||
case "unixmilli":
|
||||
t = time.UnixMilli(tv)
|
||||
case "unixmicro":
|
||||
t = time.UnixMicro(tv)
|
||||
default:
|
||||
t = time.Unix(0, tv)
|
||||
}
|
||||
|
||||
t := time.Unix(tv/int64(d), tv%int64(d))
|
||||
value.Set(reflect.ValueOf(t))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ package binding
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"errors"
|
||||
"mime/multipart"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -494,7 +494,7 @@ type customUnmarshalParamType struct {
|
||||
func (f *customUnmarshalParamType) UnmarshalParam(param string) error {
|
||||
parts := strings.Split(param, ":")
|
||||
if len(parts) != 3 {
|
||||
return fmt.Errorf("invalid format")
|
||||
return errors.New("invalid format")
|
||||
}
|
||||
f.Protocol = parts[0]
|
||||
f.Path = parts[1]
|
||||
@@ -509,9 +509,9 @@ func TestMappingCustomStructTypeWithFormTag(t *testing.T) {
|
||||
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, "file", s.FileData.Protocol)
|
||||
assert.EqualValues(t, "/foo", s.FileData.Path)
|
||||
assert.EqualValues(t, "happiness", s.FileData.Name)
|
||||
assert.Equal(t, "file", s.FileData.Protocol)
|
||||
assert.Equal(t, "/foo", s.FileData.Path)
|
||||
assert.Equal(t, "happiness", s.FileData.Name)
|
||||
}
|
||||
|
||||
func TestMappingCustomStructTypeWithURITag(t *testing.T) {
|
||||
@@ -521,9 +521,9 @@ func TestMappingCustomStructTypeWithURITag(t *testing.T) {
|
||||
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, "file", s.FileData.Protocol)
|
||||
assert.EqualValues(t, "/foo", s.FileData.Path)
|
||||
assert.EqualValues(t, "happiness", s.FileData.Name)
|
||||
assert.Equal(t, "file", s.FileData.Protocol)
|
||||
assert.Equal(t, "/foo", s.FileData.Path)
|
||||
assert.Equal(t, "happiness", s.FileData.Name)
|
||||
}
|
||||
|
||||
func TestMappingCustomPointerStructTypeWithFormTag(t *testing.T) {
|
||||
@@ -533,9 +533,9 @@ func TestMappingCustomPointerStructTypeWithFormTag(t *testing.T) {
|
||||
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, "file", s.FileData.Protocol)
|
||||
assert.EqualValues(t, "/foo", s.FileData.Path)
|
||||
assert.EqualValues(t, "happiness", s.FileData.Name)
|
||||
assert.Equal(t, "file", s.FileData.Protocol)
|
||||
assert.Equal(t, "/foo", s.FileData.Path)
|
||||
assert.Equal(t, "happiness", s.FileData.Name)
|
||||
}
|
||||
|
||||
func TestMappingCustomPointerStructTypeWithURITag(t *testing.T) {
|
||||
@@ -545,9 +545,9 @@ func TestMappingCustomPointerStructTypeWithURITag(t *testing.T) {
|
||||
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, "file", s.FileData.Protocol)
|
||||
assert.EqualValues(t, "/foo", s.FileData.Path)
|
||||
assert.EqualValues(t, "happiness", s.FileData.Name)
|
||||
assert.Equal(t, "file", s.FileData.Protocol)
|
||||
assert.Equal(t, "/foo", s.FileData.Path)
|
||||
assert.Equal(t, "happiness", s.FileData.Name)
|
||||
}
|
||||
|
||||
type customPath []string
|
||||
@@ -556,7 +556,7 @@ func (p *customPath) UnmarshalParam(param string) error {
|
||||
elems := strings.Split(param, "/")
|
||||
n := len(elems)
|
||||
if n < 2 {
|
||||
return fmt.Errorf("invalid format")
|
||||
return errors.New("invalid format")
|
||||
}
|
||||
|
||||
*p = elems
|
||||
@@ -570,8 +570,8 @@ func TestMappingCustomSliceUri(t *testing.T) {
|
||||
err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "uri")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, "bar", s.FileData[0])
|
||||
assert.EqualValues(t, "foo", s.FileData[1])
|
||||
assert.Equal(t, "bar", s.FileData[0])
|
||||
assert.Equal(t, "foo", s.FileData[1])
|
||||
}
|
||||
|
||||
func TestMappingCustomSliceForm(t *testing.T) {
|
||||
@@ -581,8 +581,8 @@ func TestMappingCustomSliceForm(t *testing.T) {
|
||||
err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "form")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, "bar", s.FileData[0])
|
||||
assert.EqualValues(t, "foo", s.FileData[1])
|
||||
assert.Equal(t, "bar", s.FileData[0])
|
||||
assert.Equal(t, "foo", s.FileData[1])
|
||||
}
|
||||
|
||||
type objectID [12]byte
|
||||
@@ -600,7 +600,7 @@ func (o *objectID) UnmarshalParam(param string) error {
|
||||
func convertTo(s string) (objectID, error) {
|
||||
var nilObjectID objectID
|
||||
if len(s) != 24 {
|
||||
return nilObjectID, fmt.Errorf("invalid format")
|
||||
return nilObjectID, errors.New("invalid format")
|
||||
}
|
||||
|
||||
var oid [12]byte
|
||||
@@ -621,7 +621,7 @@ func TestMappingCustomArrayUri(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
expected, _ := convertTo(val)
|
||||
assert.EqualValues(t, expected, s.FileData)
|
||||
assert.Equal(t, expected, s.FileData)
|
||||
}
|
||||
|
||||
func TestMappingCustomArrayForm(t *testing.T) {
|
||||
@@ -633,5 +633,5 @@ func TestMappingCustomArrayForm(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
expected, _ := convertTo(val)
|
||||
assert.EqualValues(t, expected, s.FileData)
|
||||
assert.Equal(t, expected, s.FileData)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ func (headerBinding) Name() string {
|
||||
}
|
||||
|
||||
func (headerBinding) Bind(req *http.Request, obj any) error {
|
||||
|
||||
if err := mapHeader(obj, req.Header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"git.company.lan/gopkg/gin/internal/json"
|
||||
"git.company.lan/gopkg/gin/codec/json"
|
||||
)
|
||||
|
||||
// EnableDecoderUseNumber is used to call the UseNumber method on the JSON
|
||||
@@ -42,7 +42,7 @@ func (jsonBinding) BindBody(body []byte, obj any) error {
|
||||
}
|
||||
|
||||
func decodeJSON(r io.Reader, obj any) error {
|
||||
decoder := json.NewDecoder(r)
|
||||
decoder := json.API.NewDecoder(r)
|
||||
if EnableDecoderUseNumber {
|
||||
decoder.UseNumber()
|
||||
}
|
||||
|
||||
@@ -5,8 +5,16 @@
|
||||
package binding
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"git.company.lan/gopkg/gin/codec/json"
|
||||
"git.company.lan/gopkg/gin/render"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/modern-go/reflect2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -28,3 +36,181 @@ func TestJSONBindingBindBodyMap(t *testing.T) {
|
||||
assert.Equal(t, "FOO", s["foo"])
|
||||
assert.Equal(t, "world", s["hello"])
|
||||
}
|
||||
|
||||
func TestCustomJsonCodec(t *testing.T) {
|
||||
// Restore json encoding configuration after testing
|
||||
oldMarshal := json.API
|
||||
defer func() {
|
||||
json.API = oldMarshal
|
||||
}()
|
||||
// Custom json api
|
||||
json.API = customJsonApi{}
|
||||
|
||||
// test decode json
|
||||
obj := customReq{}
|
||||
err := jsonBinding{}.BindBody([]byte(`{"time_empty":null,"time_struct": "2001-12-05 10:01:02.345","time_nil":null,"time_pointer":"2002-12-05 10:01:02.345"}`), &obj)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, zeroTime, obj.TimeEmpty)
|
||||
assert.Equal(t, time.Date(2001, 12, 5, 10, 1, 2, 345000000, time.Local), obj.TimeStruct)
|
||||
assert.Nil(t, obj.TimeNil)
|
||||
assert.Equal(t, time.Date(2002, 12, 5, 10, 1, 2, 345000000, time.Local), *obj.TimePointer)
|
||||
// test encode json
|
||||
w := httptest.NewRecorder()
|
||||
err2 := (render.PureJSON{Data: obj}).Render(w)
|
||||
require.NoError(t, err2)
|
||||
assert.JSONEq(t, "{\"time_empty\":null,\"time_struct\":\"2001-12-05 10:01:02.345\",\"time_nil\":null,\"time_pointer\":\"2002-12-05 10:01:02.345\"}\n", w.Body.String())
|
||||
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
type customReq struct {
|
||||
TimeEmpty time.Time `json:"time_empty"`
|
||||
TimeStruct time.Time `json:"time_struct"`
|
||||
TimeNil *time.Time `json:"time_nil"`
|
||||
TimePointer *time.Time `json:"time_pointer"`
|
||||
}
|
||||
|
||||
var customConfig = jsoniter.Config{
|
||||
EscapeHTML: true,
|
||||
SortMapKeys: true,
|
||||
ValidateJsonRawMessage: true,
|
||||
}.Froze()
|
||||
|
||||
func init() {
|
||||
customConfig.RegisterExtension(&TimeEx{})
|
||||
customConfig.RegisterExtension(&TimePointerEx{})
|
||||
}
|
||||
|
||||
type customJsonApi struct{}
|
||||
|
||||
func (j customJsonApi) Marshal(v any) ([]byte, error) {
|
||||
return customConfig.Marshal(v)
|
||||
}
|
||||
|
||||
func (j customJsonApi) Unmarshal(data []byte, v any) error {
|
||||
return customConfig.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
func (j customJsonApi) MarshalIndent(v any, prefix, indent string) ([]byte, error) {
|
||||
return customConfig.MarshalIndent(v, prefix, indent)
|
||||
}
|
||||
|
||||
func (j customJsonApi) NewEncoder(writer io.Writer) json.Encoder {
|
||||
return customConfig.NewEncoder(writer)
|
||||
}
|
||||
|
||||
func (j customJsonApi) NewDecoder(reader io.Reader) json.Decoder {
|
||||
return customConfig.NewDecoder(reader)
|
||||
}
|
||||
|
||||
// region Time Extension
|
||||
|
||||
var (
|
||||
zeroTime = time.Time{}
|
||||
timeType = reflect2.TypeOfPtr((*time.Time)(nil)).Elem()
|
||||
defaultTimeCodec = &timeCodec{}
|
||||
)
|
||||
|
||||
type TimeEx struct {
|
||||
jsoniter.DummyExtension
|
||||
}
|
||||
|
||||
func (te *TimeEx) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
|
||||
if typ == timeType {
|
||||
return defaultTimeCodec
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *TimeEx) CreateEncoder(typ reflect2.Type) jsoniter.ValEncoder {
|
||||
if typ == timeType {
|
||||
return defaultTimeCodec
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type timeCodec struct{}
|
||||
|
||||
func (tc timeCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
t := *((*time.Time)(ptr))
|
||||
return t.Equal(zeroTime)
|
||||
}
|
||||
|
||||
func (tc timeCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
t := *((*time.Time)(ptr))
|
||||
if t.Equal(zeroTime) {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
stream.WriteString(t.In(time.Local).Format("2006-01-02 15:04:05.000"))
|
||||
}
|
||||
|
||||
func (tc timeCodec) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
ts := iter.ReadString()
|
||||
if len(ts) == 0 {
|
||||
*((*time.Time)(ptr)) = zeroTime
|
||||
return
|
||||
}
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04:05.000", ts, time.Local)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*((*time.Time)(ptr)) = t
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region *Time Extension
|
||||
|
||||
var (
|
||||
timePointerType = reflect2.TypeOfPtr((**time.Time)(nil)).Elem()
|
||||
defaultTimePointerCodec = &timePointerCodec{}
|
||||
)
|
||||
|
||||
type TimePointerEx struct {
|
||||
jsoniter.DummyExtension
|
||||
}
|
||||
|
||||
func (tpe *TimePointerEx) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
|
||||
if typ == timePointerType {
|
||||
return defaultTimePointerCodec
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tpe *TimePointerEx) CreateEncoder(typ reflect2.Type) jsoniter.ValEncoder {
|
||||
if typ == timePointerType {
|
||||
return defaultTimePointerCodec
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type timePointerCodec struct{}
|
||||
|
||||
func (tpc timePointerCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
t := *((**time.Time)(ptr))
|
||||
return t == nil || (*t).Equal(zeroTime)
|
||||
}
|
||||
|
||||
func (tpc timePointerCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
t := *((**time.Time)(ptr))
|
||||
if t == nil || (*t).Equal(zeroTime) {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
stream.WriteString(t.In(time.Local).Format("2006-01-02 15:04:05.000"))
|
||||
}
|
||||
|
||||
func (tpc timePointerCodec) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
ts := iter.ReadString()
|
||||
if len(ts) == 0 {
|
||||
*((**time.Time)(ptr)) = nil
|
||||
return
|
||||
}
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04:05.000", ts, time.Local)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*((**time.Time)(ptr)) = &t
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
@@ -116,7 +116,7 @@ func createRequestMultipartFiles(t *testing.T, files ...testFile) *http.Request
|
||||
err := mw.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
req, err := http.NewRequest("POST", "/", &body)
|
||||
req, err := http.NewRequest(http.MethodPost, "/", &body)
|
||||
require.NoError(t, err)
|
||||
|
||||
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+mw.Boundary())
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ func (plainBinding) Name() string {
|
||||
return "plain"
|
||||
}
|
||||
|
||||
func (plainBinding) Bind(req *http.Request, obj interface{}) error {
|
||||
func (plainBinding) Bind(req *http.Request, obj any) error {
|
||||
all, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ func (protobufBinding) BindBody(body []byte, obj any) error {
|
||||
if err := proto.Unmarshal(body, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
// Here it's same to return validate(obj), but util now we can't add
|
||||
// Here it's same to return validate(obj), but until now we can't add
|
||||
// `binding:""` to the struct which automatically generate by gen-proto
|
||||
return nil
|
||||
// return validate(obj)
|
||||
|
||||
+1
-1
@@ -31,5 +31,5 @@ func decodeToml(r io.Reader, obj any) error {
|
||||
if err := decoder.Decode(obj); err != nil {
|
||||
return err
|
||||
}
|
||||
return decoder.Decode(obj)
|
||||
return validate(obj)
|
||||
}
|
||||
|
||||
@@ -158,16 +158,16 @@ type structNoValidationPointer struct {
|
||||
}
|
||||
|
||||
func TestValidateNoValidationPointers(t *testing.T) {
|
||||
//origin := createNoValidation_values()
|
||||
//test := createNoValidation_values()
|
||||
// origin := createNoValidation_values()
|
||||
// test := createNoValidation_values()
|
||||
empty := structNoValidationPointer{}
|
||||
|
||||
//assert.Nil(t, validate(test))
|
||||
//assert.Nil(t, validate(&test))
|
||||
// assert.Nil(t, validate(test))
|
||||
// assert.Nil(t, validate(&test))
|
||||
require.NoError(t, validate(empty))
|
||||
require.NoError(t, validate(&empty))
|
||||
|
||||
//assert.Equal(t, origin, test)
|
||||
// assert.Equal(t, origin, test)
|
||||
}
|
||||
|
||||
type Object map[string]any
|
||||
@@ -198,7 +198,7 @@ type structModifyValidation struct {
|
||||
}
|
||||
|
||||
func toZero(sl validator.StructLevel) {
|
||||
var s *structModifyValidation = sl.Top().Interface().(*structModifyValidation)
|
||||
s := sl.Top().Interface().(*structModifyValidation)
|
||||
s.Integer = 0
|
||||
}
|
||||
|
||||
@@ -249,5 +249,5 @@ func TestValidatorEngine(t *testing.T) {
|
||||
// Check that we got back non-nil errs
|
||||
require.Error(t, errs)
|
||||
// Check that the error matches expectation
|
||||
require.Error(t, errs, "", "", "notone")
|
||||
require.Error(t, errs, "notone")
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ func (xmlBinding) Bind(req *http.Request, obj any) error {
|
||||
func (xmlBinding) BindBody(body []byte, obj any) error {
|
||||
return decodeXML(bytes.NewReader(body), obj)
|
||||
}
|
||||
|
||||
func decodeXML(r io.Reader, obj any) error {
|
||||
decoder := xml.NewDecoder(r)
|
||||
if err := decoder.Decode(obj); err != nil {
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/goccy/go-yaml"
|
||||
)
|
||||
|
||||
type yamlBinding struct{}
|
||||
|
||||
Reference in New Issue
Block a user