Add interface to read body bytes in binding

This commit is contained in:
delphinus 2018-04-29 15:15:23 +09:00
parent 2282be059b
commit 3ae520b45c
2 changed files with 32 additions and 0 deletions

View File

@ -29,6 +29,13 @@ type Binding interface {
Bind(*http.Request, interface{}) error Bind(*http.Request, interface{}) error
} }
// BindingBody adds BindBody method to Binding. BindBody is similar with Bind,
// but it reads the body from supplied bytes instead of req.Body.
type BindingBody interface {
Binding
BindBody([]byte, interface{}) error
}
// StructValidator is the minimal interface which needs to be implemented in // StructValidator is the minimal interface which needs to be implemented in
// order for it to be used as the validator engine for ensuring the correctness // order for it to be used as the validator engine for ensuring the correctness
// of the reqest. Gin provides a default implementation for this using // of the reqest. Gin provides a default implementation for this using

View File

@ -31,6 +31,7 @@ const (
MIMEPlain = binding.MIMEPlain MIMEPlain = binding.MIMEPlain
MIMEPOSTForm = binding.MIMEPOSTForm MIMEPOSTForm = binding.MIMEPOSTForm
MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
BodyBytesKey = "github.com/gin-gonic/gin/bodyBytes"
) )
const abortIndex int8 = math.MaxInt8 / 2 const abortIndex int8 = math.MaxInt8 / 2
@ -508,6 +509,30 @@ func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error {
return b.Bind(c.Request, obj) return b.Bind(c.Request, obj)
} }
// ShouldBindBodyWith is similar with ShouldBindWith, but it stores the request
// body into the context, and reuse when it is called again.
//
// NOTE: This method reads the body before binding. So you should use
// ShouldBindWith for better performance if you need to call only once.
func (c *Context) ShouldBindBodyWith(
obj interface{}, bb binding.BindingBody,
) (err error) {
var body []byte
if cb, ok := c.Get(BodyBytesKey); ok {
if cbb, ok := cb.([]byte); ok {
body = cbb
}
}
if body == nil {
body, err = ioutil.ReadAll(c.Request.Body)
if err != nil {
return err
}
c.Set(BodyBytesKey, body)
}
return bb.BindBody(body, obj)
}
// ClientIP implements a best effort algorithm to return the real client IP, it parses // ClientIP implements a best effort algorithm to return the real client IP, it parses
// X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy. // X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy.
// Use X-Forwarded-For before X-Real-Ip as nginx uses X-Real-Ip with the proxy's IP. // Use X-Forwarded-For before X-Real-Ip as nginx uses X-Real-Ip with the proxy's IP.