mirror of
https://github.com/gin-gonic/gin.git
synced 2026-09-11 03:48:05 +08:00
#4759 introducing a general body limit to avoid big heap allocations
This commit is contained in:
parent
34dac209ff
commit
ad91108a5b
15
context.go
15
context.go
@ -940,6 +940,7 @@ func (c *Context) ShouldBindUri(obj any) error {
|
||||
// ShouldBindWith binds the passed struct pointer using the specified binding engine.
|
||||
// See the binding package.
|
||||
func (c *Context) ShouldBindWith(obj any, b binding.Binding) error {
|
||||
c.limitRequestBody()
|
||||
return b.Bind(c.Request, obj)
|
||||
}
|
||||
|
||||
@ -949,6 +950,7 @@ func (c *Context) ShouldBindWith(obj any, b binding.Binding) error {
|
||||
// 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 any, bb binding.BindingBody) (err error) {
|
||||
c.limitRequestBody()
|
||||
var body []byte
|
||||
if cb, ok := c.Get(BodyBytesKey); ok {
|
||||
if cbb, ok := cb.([]byte); ok {
|
||||
@ -965,6 +967,19 @@ func (c *Context) ShouldBindBodyWith(obj any, bb binding.BindingBody) (err error
|
||||
return bb.BindBody(body, obj)
|
||||
}
|
||||
|
||||
// limitRequestBody wraps c.Request.Body in place so that reading more than
|
||||
// c.engine.MaxRequestBodyBytes from it fails with *http.MaxBytesError, which
|
||||
// MustBindWith already maps to a 413 response.
|
||||
func (c *Context) limitRequestBody() {
|
||||
if c.engine == nil || c.engine.MaxRequestBodyBytes <= 0 {
|
||||
return
|
||||
}
|
||||
if c.Request == nil || c.Request.Body == nil {
|
||||
return
|
||||
}
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, c.engine.MaxRequestBodyBytes)
|
||||
}
|
||||
|
||||
// ShouldBindBodyWithJSON is a shortcut for c.ShouldBindBodyWith(obj, binding.JSON).
|
||||
func (c *Context) ShouldBindBodyWithJSON(obj any) error {
|
||||
return c.ShouldBindBodyWith(obj, binding.JSON)
|
||||
|
||||
17
gin.go
17
gin.go
@ -23,10 +23,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMultipartMemory = 32 << 20 // 32 MB
|
||||
escapedColon = "\\:"
|
||||
colon = ":"
|
||||
backslash = "\\"
|
||||
defaultMultipartMemory = 32 << 20 // 32 MB
|
||||
defaultMaxRequestBodyBytes = 128 << 20 // 128 MiB
|
||||
escapedColon = "\\:"
|
||||
colon = ":"
|
||||
backslash = "\\"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -166,6 +167,13 @@ type Engine struct {
|
||||
// method call.
|
||||
MaxMultipartMemory int64
|
||||
|
||||
// MaxRequestBodyBytes limits how many bytes Context's Bind*/ShouldBind*/
|
||||
// ShouldBindBodyWith* methods will read from a request body before failing
|
||||
// with a 413. It protects against a client sending an oversized or
|
||||
// malformed body that would otherwise be buffered into memory in full
|
||||
// before being rejected. Set to <= 0 to disable and read bodies unbounded.
|
||||
MaxRequestBodyBytes int64
|
||||
|
||||
// UseH2C enable h2c support.
|
||||
UseH2C bool
|
||||
|
||||
@ -219,6 +227,7 @@ func New(opts ...OptionFunc) *Engine {
|
||||
RemoveExtraSlash: false,
|
||||
UnescapePathValues: true,
|
||||
MaxMultipartMemory: defaultMultipartMemory,
|
||||
MaxRequestBodyBytes: defaultMaxRequestBodyBytes,
|
||||
trees: make(methodTrees, 0, 9),
|
||||
delims: render.Delims{Left: "{{", Right: "}}"},
|
||||
secureJSONPrefix: "while(1);",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user