feat(context): add BindQuery func (#1029)

* feat(context): add BindQuery func, only parse/bind the query string params.

* docs(readme): add BindQuery section.

* docs(readme): fix import.

* docs(readme): separate import
This commit is contained in:
Eason Lin 2017-07-19 15:50:05 +08:00 committed by Javier Provecho Fernandez
parent 74221b8a35
commit c19aa0598b
6 changed files with 109 additions and 1 deletions

View File

@ -460,7 +460,43 @@ func main() {
} }
``` ```
### Bind Query String ### Only Bind Query String
`BindQuery` function only binds the query params and not the post data. See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-315953017).
```go
package main
import (
"log"
"github.com/gin-gonic/gin"
)
type Person struct {
Name string `form:"name"`
Address string `form:"address"`
}
func main() {
route := gin.Default()
route.Any("/testing", startPage)
route.Run(":8085")
}
func startPage(c *gin.Context) {
var person Person
if c.BindQuery(&person) == nil {
log.Println("====== Only Bind By Query String ======")
log.Println(person.Name)
log.Println(person.Address)
}
c.String(200, "Success")
}
```
### Bind Query String or Post Data
See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292). See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292).

View File

@ -39,6 +39,7 @@ var (
JSON = jsonBinding{} JSON = jsonBinding{}
XML = xmlBinding{} XML = xmlBinding{}
Form = formBinding{} Form = formBinding{}
Query = queryBinding{}
FormPost = formPostBinding{} FormPost = formPostBinding{}
FormMultipart = formMultipartBinding{} FormMultipart = formMultipartBinding{}
ProtoBuf = protobufBinding{} ProtoBuf = protobufBinding{}

View File

@ -67,6 +67,18 @@ func TestBindingForm2(t *testing.T) {
"", "") "", "")
} }
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", "")
}
func TestBindingXML(t *testing.T) { func TestBindingXML(t *testing.T) {
testBodyBinding(t, testBodyBinding(t,
XML, "xml", XML, "xml",
@ -204,6 +216,21 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
assert.Error(t, err) assert.Error(t, err)
} }
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")
}
func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
assert.Equal(t, b.Name(), name) assert.Equal(t, b.Name(), name)

23
binding/query.go Normal file
View File

@ -0,0 +1,23 @@
// Copyright 2017 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 (
"net/http"
)
type queryBinding struct{}
func (queryBinding) Name() string {
return "query"
}
func (queryBinding) Bind(req *http.Request, obj interface{}) error {
values := req.URL.Query()
if err := mapForm(obj, values); err != nil {
return err
}
return validate(obj)
}

View File

@ -467,6 +467,11 @@ func (c *Context) BindJSON(obj interface{}) error {
return c.MustBindWith(obj, binding.JSON) return c.MustBindWith(obj, binding.JSON)
} }
// BindQuery is a shortcut for c.MustBindWith(obj, binding.Query)
func (c *Context) BindQuery(obj interface{}) error {
return c.MustBindWith(obj, binding.Query)
}
// MustBindWith binds the passed struct pointer using the specified binding // MustBindWith binds the passed struct pointer using the specified binding
// engine. It will abort the request with HTTP 400 if any error ocurrs. // engine. It will abort the request with HTTP 400 if any error ocurrs.
// See the binding package. // See the binding package.

View File

@ -1186,6 +1186,22 @@ func TestContextBindWithJSON(t *testing.T) {
assert.Equal(t, w.Body.Len(), 0) assert.Equal(t, w.Body.Len(), 0)
} }
func TestContextBindWithQuery(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
var obj struct {
Foo string `form:"foo"`
Bar string `form:"bar"`
}
assert.NoError(t, c.BindQuery(&obj))
assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len())
}
func TestContextBadAutoBind(t *testing.T) { func TestContextBadAutoBind(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
c, _ := CreateTestContext(w) c, _ := CreateTestContext(w)