From 9eff3ec358132eb4d33b9ec691a5d4111294a70e Mon Sep 17 00:00:00 2001 From: Ghost Date: Sat, 2 Mar 2024 13:38:24 +0800 Subject: [PATCH 1/5] feat: ShouldBindBodyWith shortcut and change doc --- context.go | 20 +++++ context_test.go | 204 ++++++++++++++++++++++++++++++++++++++++++++++++ docs/doc.md | 9 ++- 3 files changed, 231 insertions(+), 2 deletions(-) diff --git a/context.go b/context.go index 420ff1678f..c5723f3874 100644 --- a/context.go +++ b/context.go @@ -763,6 +763,26 @@ func (c *Context) ShouldBindBodyWith(obj any, bb binding.BindingBody) (err error 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. // 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]). diff --git a/context_test.go b/context_test.go index 88165c07c9..b3ebb2b7ff 100644 --- a/context_test.go +++ b/context_test.go @@ -1975,6 +1975,210 @@ 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: ` + +FOO +`, + }, + { + 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.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) + assert.Equal(t, typeJSON{}, objJSON) + } else { + assert.NoError(t, c.ShouldBindBodyWithJSON(&objJSON)) + assert.Equal(t, typeJSON{"FOO"}, 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: ` + +FOO +`, + }, + { + 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.XML { + assert.Error(t, c.ShouldBindBodyWithXML(&objXML)) + assert.Equal(t, typeXML{}, objXML) + } else { + assert.NoError(t, c.ShouldBindBodyWithXML(&objXML)) + assert.Equal(t, typeXML{"FOO"}, 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: ` + +FOO +`, + }, + { + 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{} + if tt.bindingBody != binding.YAML { + assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML)) + assert.Equal(t, typeYAML{}, objYAML) + } else { + assert.NoError(t, c.ShouldBindBodyWithYAML(&objYAML)) + assert.Equal(t, typeYAML{"FOO"}, 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: ` + +FOO +`, + }, + { + 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.TOML { + assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML)) + assert.Equal(t, typeTOML{}, objTOML) + } else { + assert.NoError(t, c.ShouldBindBodyWithTOML(&objTOML)) + assert.Equal(t, typeTOML{"FOO"}, objTOML) + } + } +} + func TestContextGolangContext(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}")) diff --git a/docs/doc.md b/docs/doc.md index df006e87a7..70c9f27540 100644 --- a/docs/doc.md +++ b/docs/doc.md @@ -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 func SomeHandler(c *gin.Context) { @@ -1969,7 +1974,7 @@ func SomeHandler(c *gin.Context) { } else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil { c.String(http.StatusOK, `the body should be formB JSON`) // 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`) } else { ... From 62e0e95e28c1517522cd11badfc29b5a37dc04d2 Mon Sep 17 00:00:00 2001 From: Ghost Date: Tue, 12 Mar 2024 15:24:10 +0800 Subject: [PATCH 2/5] fix: yaml can parse json test case --- context_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/context_test.go b/context_test.go index b3ebb2b7ff..83e9524215 100644 --- a/context_test.go +++ b/context_test.go @@ -2118,7 +2118,7 @@ func TestContextShouldBindBodyWithYAML(t *testing.T) { Foo string `yaml:"foo" binding:"required"` } objYAML := typeYAML{} - if tt.bindingBody != binding.YAML { + if tt.bindingBody != binding.YAML && tt.bindingBody != binding.JSON { assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML)) assert.Equal(t, typeYAML{}, objYAML) } else { From 26952eb3b0840b391efd30ef238c8c56f9308ba5 Mon Sep 17 00:00:00 2001 From: Ghost Date: Thu, 14 Mar 2024 18:24:35 +0800 Subject: [PATCH 3/5] style: fix new test case in context_test.go --- context_test.go | 88 ++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/context_test.go b/context_test.go index 83e9524215..863074fe33 100644 --- a/context_test.go +++ b/context_test.go @@ -1977,32 +1977,32 @@ func TestContextShouldBindBodyWith(t *testing.T) { func TestContextShouldBindBodyWithJSON(t *testing.T) { for _, tt := range []struct { - name string - bindingBody binding.BindingBody - body string + name string + bindingBody binding.BindingBody + body string }{ { - name: " JSON & JSON-BODY ", + name: " JSON & JSON-BODY ", bindingBody: binding.JSON, - body: `{"foo":"FOO"}`, + body: `{"foo":"FOO"}`, }, { - name: " JSON & XML-BODY ", + name: " JSON & XML-BODY ", bindingBody: binding.XML, - body: ` + body: ` FOO `, }, { - name: " JSON & YAML-BODY ", + name: " JSON & YAML-BODY ", bindingBody: binding.YAML, - body: `foo: FOO`, + body: `foo: FOO`, }, { - name: " JSON & TOM-BODY ", + name: " JSON & TOM-BODY ", bindingBody: binding.TOML, - body: `foo=FOO`, + body: `foo=FOO`, }, } { t.Logf("testing: %s", tt.name) @@ -2028,32 +2028,32 @@ func TestContextShouldBindBodyWithJSON(t *testing.T) { func TestContextShouldBindBodyWithXML(t *testing.T) { for _, tt := range []struct { - name string - bindingBody binding.BindingBody - body string + name string + bindingBody binding.BindingBody + body string }{ { - name: " XML & JSON-BODY ", + name: " XML & JSON-BODY ", bindingBody: binding.JSON, - body: `{"foo":"FOO"}`, + body: `{"foo":"FOO"}`, }, { - name: " XML & XML-BODY ", + name: " XML & XML-BODY ", bindingBody: binding.XML, - body: ` + body: ` FOO `, }, { - name: " XML & YAML-BODY ", + name: " XML & YAML-BODY ", bindingBody: binding.YAML, - body: `foo: FOO`, + body: `foo: FOO`, }, { - name: " XML & TOM-BODY ", + name: " XML & TOM-BODY ", bindingBody: binding.TOML, - body: `foo=FOO`, + body: `foo=FOO`, }, } { t.Logf("testing: %s", tt.name) @@ -2079,32 +2079,32 @@ func TestContextShouldBindBodyWithXML(t *testing.T) { func TestContextShouldBindBodyWithYAML(t *testing.T) { for _, tt := range []struct { - name string - bindingBody binding.BindingBody - body string + name string + bindingBody binding.BindingBody + body string }{ { - name: " YAML & JSON-BODY ", + name: " YAML & JSON-BODY ", bindingBody: binding.JSON, - body: `{"foo":"FOO"}`, + body: `{"foo":"FOO"}`, }, { - name: " YAML & XML-BODY ", + name: " YAML & XML-BODY ", bindingBody: binding.XML, - body: ` + body: ` FOO `, }, { - name: " YAML & YAML-BODY ", + name: " YAML & YAML-BODY ", bindingBody: binding.YAML, - body: `foo: FOO`, + body: `foo: FOO`, }, { - name: " YAML & TOM-BODY ", + name: " YAML & TOM-BODY ", bindingBody: binding.TOML, - body: `foo=FOO`, + body: `foo=FOO`, }, } { t.Logf("testing: %s", tt.name) @@ -2130,32 +2130,32 @@ func TestContextShouldBindBodyWithYAML(t *testing.T) { func TestContextShouldBindBodyWithTOML(t *testing.T) { for _, tt := range []struct { - name string - bindingBody binding.BindingBody - body string + name string + bindingBody binding.BindingBody + body string }{ { - name: " TOML & JSON-BODY ", + name: " TOML & JSON-BODY ", bindingBody: binding.JSON, - body: `{"foo":"FOO"}`, + body: `{"foo":"FOO"}`, }, { - name: " TOML & XML-BODY ", + name: " TOML & XML-BODY ", bindingBody: binding.XML, - body: ` + body: ` FOO `, }, { - name: " TOML & YAML-BODY ", + name: " TOML & YAML-BODY ", bindingBody: binding.YAML, - body: `foo: FOO`, + body: `foo: FOO`, }, { - name: " TOML & TOM-BODY ", + name: " TOML & TOM-BODY ", bindingBody: binding.TOML, - body: `foo = 'FOO'`, + body: `foo = 'FOO'`, }, } { t.Logf("testing: %s", tt.name) From 891b33f8888f1e976cb9bfcbc57c97d2fc4416b5 Mon Sep 17 00:00:00 2001 From: Ghost Date: Fri, 22 Mar 2024 14:11:44 +0800 Subject: [PATCH 4/5] chore: modify the code style to specify binding type --- context_test.go | 73 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/context_test.go b/context_test.go index 863074fe33..68c1dd2e08 100644 --- a/context_test.go +++ b/context_test.go @@ -2016,13 +2016,26 @@ func TestContextShouldBindBodyWithJSON(t *testing.T) { Foo string `json:"foo" binding:"required"` } objJSON := typeJSON{} - if tt.bindingBody != binding.JSON { - assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) - assert.Equal(t, typeJSON{}, objJSON) - } else { + + 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) + } } } @@ -2067,13 +2080,26 @@ func TestContextShouldBindBodyWithXML(t *testing.T) { Foo string `xml:"foo" binding:"required"` } objXML := typeXML{} - if tt.bindingBody != binding.XML { + + if tt.bindingBody == binding.JSON { assert.Error(t, c.ShouldBindBodyWithXML(&objXML)) assert.Equal(t, typeXML{}, objXML) - } else { + } + + 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) + } } } @@ -2118,13 +2144,27 @@ func TestContextShouldBindBodyWithYAML(t *testing.T) { Foo string `yaml:"foo" binding:"required"` } objYAML := typeYAML{} - if tt.bindingBody != binding.YAML && tt.bindingBody != binding.JSON { + + // 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) - } else { + } + + 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) + } } } @@ -2169,10 +2209,23 @@ func TestContextShouldBindBodyWithTOML(t *testing.T) { Foo string `toml:"foo" binding:"required"` } objTOML := typeTOML{} - if tt.bindingBody != binding.TOML { + + 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) - } else { + } + + 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) } From d7acf06fbac46feb5500ead790872a785e3b3185 Mon Sep 17 00:00:00 2001 From: Ghost Date: Sat, 23 Mar 2024 16:51:37 +0800 Subject: [PATCH 5/5] chroe: gofmt modifies the code format --- context_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/context_test.go b/context_test.go index 68c1dd2e08..5149db3644 100644 --- a/context_test.go +++ b/context_test.go @@ -2017,7 +2017,7 @@ func TestContextShouldBindBodyWithJSON(t *testing.T) { } objJSON := typeJSON{} - if tt.bindingBody == binding.JSON{ + if tt.bindingBody == binding.JSON { assert.NoError(t, c.ShouldBindBodyWithJSON(&objJSON)) assert.Equal(t, typeJSON{"FOO"}, objJSON) } @@ -2091,7 +2091,7 @@ func TestContextShouldBindBodyWithXML(t *testing.T) { assert.Equal(t, typeXML{"FOO"}, objXML) } - if tt.bindingBody == binding.YAML{ + if tt.bindingBody == binding.YAML { assert.Error(t, c.ShouldBindBodyWithXML(&objXML)) assert.Equal(t, typeXML{}, objXML) }