Merge branch 'gin-gonic:master' into options

This commit is contained in:
Flc゛ 2024-03-23 22:26:54 +08:00 committed by GitHub
commit 72d213170f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 296 additions and 14 deletions

View File

@ -73,18 +73,18 @@ var Validator StructValidator = &defaultValidator{}
// These implement the Binding interface and can be used to bind the data // These implement the Binding interface and can be used to bind the data
// present in the request to struct instances. // present in the request to struct instances.
var ( var (
JSON = jsonBinding{} JSON BindingBody = jsonBinding{}
XML = xmlBinding{} XML BindingBody = xmlBinding{}
Form = formBinding{} Form Binding = formBinding{}
Query = queryBinding{} Query Binding = queryBinding{}
FormPost = formPostBinding{} FormPost Binding = formPostBinding{}
FormMultipart = formMultipartBinding{} FormMultipart Binding = formMultipartBinding{}
ProtoBuf = protobufBinding{} ProtoBuf BindingBody = protobufBinding{}
MsgPack = msgpackBinding{} MsgPack BindingBody = msgpackBinding{}
YAML = yamlBinding{} YAML BindingBody = yamlBinding{}
Uri = uriBinding{} Uri BindingUri = uriBinding{}
Header = headerBinding{} Header Binding = headerBinding{}
TOML = tomlBinding{} TOML BindingBody = tomlBinding{}
) )
// Default returns the appropriate Binding instance based on the HTTP method // Default returns the appropriate Binding instance based on the HTTP method

View File

@ -774,6 +774,26 @@ func (c *Context) ShouldBindBodyWith(obj any, bb binding.BindingBody) (err error
return bb.BindBody(body, obj) return bb.BindBody(body, obj)
} }
// ShouldBindBodyWithJSON is a shortcut for c.ShouldBindBodyWith(obj, binding.JSON).
func (c *Context) ShouldBindBodyWithJSON(obj any) error {
return c.ShouldBindBodyWith(obj, binding.JSON)
}
// ShouldBindBodyWithXML is a shortcut for c.ShouldBindBodyWith(obj, binding.XML).
func (c *Context) ShouldBindBodyWithXML(obj any) error {
return c.ShouldBindBodyWith(obj, binding.XML)
}
// ShouldBindBodyWithYAML is a shortcut for c.ShouldBindBodyWith(obj, binding.YAML).
func (c *Context) ShouldBindBodyWithYAML(obj any) error {
return c.ShouldBindBodyWith(obj, binding.YAML)
}
// ShouldBindBodyWithTOML is a shortcut for c.ShouldBindBodyWith(obj, binding.TOML).
func (c *Context) ShouldBindBodyWithTOML(obj any) error {
return c.ShouldBindBodyWith(obj, binding.TOML)
}
// ClientIP implements one best effort algorithm to return the real client IP. // ClientIP implements one best effort algorithm to return the real client IP.
// It calls c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not. // It calls c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not.
// If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]). // If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]).

View File

@ -1977,6 +1977,263 @@ func TestContextShouldBindBodyWith(t *testing.T) {
} }
} }
func TestContextShouldBindBodyWithJSON(t *testing.T) {
for _, tt := range []struct {
name string
bindingBody binding.BindingBody
body string
}{
{
name: " JSON & JSON-BODY ",
bindingBody: binding.JSON,
body: `{"foo":"FOO"}`,
},
{
name: " JSON & XML-BODY ",
bindingBody: binding.XML,
body: `<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>FOO</foo>
</root>`,
},
{
name: " JSON & YAML-BODY ",
bindingBody: binding.YAML,
body: `foo: FOO`,
},
{
name: " JSON & TOM-BODY ",
bindingBody: binding.TOML,
body: `foo=FOO`,
},
} {
t.Logf("testing: %s", tt.name)
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
type typeJSON struct {
Foo string `json:"foo" binding:"required"`
}
objJSON := typeJSON{}
if tt.bindingBody == binding.JSON {
assert.NoError(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{"FOO"}, objJSON)
}
if tt.bindingBody == binding.XML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON)
}
if tt.bindingBody == binding.YAML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON)
}
if tt.bindingBody == binding.TOML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON)
}
}
}
func TestContextShouldBindBodyWithXML(t *testing.T) {
for _, tt := range []struct {
name string
bindingBody binding.BindingBody
body string
}{
{
name: " XML & JSON-BODY ",
bindingBody: binding.JSON,
body: `{"foo":"FOO"}`,
},
{
name: " XML & XML-BODY ",
bindingBody: binding.XML,
body: `<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>FOO</foo>
</root>`,
},
{
name: " XML & YAML-BODY ",
bindingBody: binding.YAML,
body: `foo: FOO`,
},
{
name: " XML & TOM-BODY ",
bindingBody: binding.TOML,
body: `foo=FOO`,
},
} {
t.Logf("testing: %s", tt.name)
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
type typeXML struct {
Foo string `xml:"foo" binding:"required"`
}
objXML := typeXML{}
if tt.bindingBody == binding.JSON {
assert.Error(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{}, objXML)
}
if tt.bindingBody == binding.XML {
assert.NoError(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{"FOO"}, objXML)
}
if tt.bindingBody == binding.YAML {
assert.Error(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{}, objXML)
}
if tt.bindingBody == binding.TOML {
assert.Error(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{}, objXML)
}
}
}
func TestContextShouldBindBodyWithYAML(t *testing.T) {
for _, tt := range []struct {
name string
bindingBody binding.BindingBody
body string
}{
{
name: " YAML & JSON-BODY ",
bindingBody: binding.JSON,
body: `{"foo":"FOO"}`,
},
{
name: " YAML & XML-BODY ",
bindingBody: binding.XML,
body: `<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>FOO</foo>
</root>`,
},
{
name: " YAML & YAML-BODY ",
bindingBody: binding.YAML,
body: `foo: FOO`,
},
{
name: " YAML & TOM-BODY ",
bindingBody: binding.TOML,
body: `foo=FOO`,
},
} {
t.Logf("testing: %s", tt.name)
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
type typeYAML struct {
Foo string `yaml:"foo" binding:"required"`
}
objYAML := typeYAML{}
// YAML belongs to a super collection of JSON, so JSON can be parsed by YAML
if tt.bindingBody == binding.JSON {
assert.NoError(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{"FOO"}, objYAML)
}
if tt.bindingBody == binding.XML {
assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{}, objYAML)
}
if tt.bindingBody == binding.YAML {
assert.NoError(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{"FOO"}, objYAML)
}
if tt.bindingBody == binding.TOML {
assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{}, objYAML)
}
}
}
func TestContextShouldBindBodyWithTOML(t *testing.T) {
for _, tt := range []struct {
name string
bindingBody binding.BindingBody
body string
}{
{
name: " TOML & JSON-BODY ",
bindingBody: binding.JSON,
body: `{"foo":"FOO"}`,
},
{
name: " TOML & XML-BODY ",
bindingBody: binding.XML,
body: `<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>FOO</foo>
</root>`,
},
{
name: " TOML & YAML-BODY ",
bindingBody: binding.YAML,
body: `foo: FOO`,
},
{
name: " TOML & TOM-BODY ",
bindingBody: binding.TOML,
body: `foo = 'FOO'`,
},
} {
t.Logf("testing: %s", tt.name)
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
type typeTOML struct {
Foo string `toml:"foo" binding:"required"`
}
objTOML := typeTOML{}
if tt.bindingBody == binding.JSON {
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{}, objTOML)
}
if tt.bindingBody == binding.XML {
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{}, objTOML)
}
if tt.bindingBody == binding.YAML {
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{}, objTOML)
}
if tt.bindingBody == binding.TOML {
assert.NoError(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{"FOO"}, objTOML)
}
}
}
func TestContextGolangContext(t *testing.T) { func TestContextGolangContext(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}")) c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))

View File

@ -1956,7 +1956,12 @@ func SomeHandler(c *gin.Context) {
} }
``` ```
For this, you can use `c.ShouldBindBodyWith`. For this, you can use `c.ShouldBindBodyWith` or shortcuts.
- `c.ShouldBindBodyWithJSON` is a shortcut for c.ShouldBindBodyWith(obj, binding.JSON).
- `c.ShouldBindBodyWithXML` is a shortcut for c.ShouldBindBodyWith(obj, binding.XML).
- `c.ShouldBindBodyWithYAML` is a shortcut for c.ShouldBindBodyWith(obj, binding.YAML).
- `c.ShouldBindBodyWithTOML` is a shortcut for c.ShouldBindBodyWith(obj, binding.TOML).
```go ```go
func SomeHandler(c *gin.Context) { func SomeHandler(c *gin.Context) {
@ -1969,7 +1974,7 @@ func SomeHandler(c *gin.Context) {
} else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil { } else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
c.String(http.StatusOK, `the body should be formB JSON`) c.String(http.StatusOK, `the body should be formB JSON`)
// And it can accepts other formats // And it can accepts other formats
} else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil { } else if errB2 := c.ShouldBindBodyWithXML(&objB); errB2 == nil {
c.String(http.StatusOK, `the body should be formB XML`) c.String(http.StatusOK, `the body should be formB XML`)
} else { } else {
... ...