mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-27 22:23:48 +03:00
requestbody: Return HTTP 413 (fix #4558)
This commit is contained in:
parent
b82e22b459
commit
3d616e8c6d
4 changed files with 25 additions and 8 deletions
|
@ -82,6 +82,9 @@ func (e HandlerError) Error() string {
|
||||||
return strings.TrimSpace(s)
|
return strings.TrimSpace(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unwrap returns the underlying error value. See the `errors` package for info.
|
||||||
|
func (e HandlerError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
// randString returns a string of n random characters.
|
// randString returns a string of n random characters.
|
||||||
// It is not even remotely secure OR a proper distribution.
|
// It is not even remotely secure OR a proper distribution.
|
||||||
// But it's good enough for some things. It excludes certain
|
// But it's good enough for some things. It excludes certain
|
||||||
|
|
|
@ -162,12 +162,8 @@ func addHTTPVarsToReplacer(repl *caddy.Replacer, req *http.Request, w http.Respo
|
||||||
// read the request body into a buffer (can't pool because we
|
// read the request body into a buffer (can't pool because we
|
||||||
// don't know its lifetime and would have to make a copy anyway)
|
// don't know its lifetime and would have to make a copy anyway)
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
_, err := io.Copy(buf, req.Body)
|
_, _ = io.Copy(buf, req.Body) // can't handle error, so just ignore it
|
||||||
if err != nil {
|
req.Body = io.NopCloser(buf) // replace real body with buffered data
|
||||||
return "", true
|
|
||||||
}
|
|
||||||
// replace real body with buffered data
|
|
||||||
req.Body = io.NopCloser(buf)
|
|
||||||
return buf.String(), true
|
return buf.String(), true
|
||||||
|
|
||||||
// original request, before any internal changes
|
// original request, before any internal changes
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package requestbody
|
package requestbody
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
|
@ -28,6 +29,7 @@ func init() {
|
||||||
// RequestBody is a middleware for manipulating the request body.
|
// RequestBody is a middleware for manipulating the request body.
|
||||||
type RequestBody struct {
|
type RequestBody struct {
|
||||||
// The maximum number of bytes to allow reading from the body by a later handler.
|
// The maximum number of bytes to allow reading from the body by a later handler.
|
||||||
|
// If more bytes are read, an error with HTTP status 413 is returned.
|
||||||
MaxSize int64 `json:"max_size,omitempty"`
|
MaxSize int64 `json:"max_size,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,10 +46,24 @@ func (rb RequestBody) ServeHTTP(w http.ResponseWriter, r *http.Request, next cad
|
||||||
return next.ServeHTTP(w, r)
|
return next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
if rb.MaxSize > 0 {
|
if rb.MaxSize > 0 {
|
||||||
r.Body = http.MaxBytesReader(w, r.Body, rb.MaxSize)
|
r.Body = errorWrapper{http.MaxBytesReader(w, r.Body, rb.MaxSize)}
|
||||||
}
|
}
|
||||||
return next.ServeHTTP(w, r)
|
return next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// errorWrapper wraps errors that are returned from Read()
|
||||||
|
// so that they can be associated with a proper status code.
|
||||||
|
type errorWrapper struct {
|
||||||
|
io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ew errorWrapper) Read(p []byte) (n int, err error) {
|
||||||
|
n, err = ew.ReadCloser.Read(p)
|
||||||
|
if err != nil && err.Error() == "http: request body too large" {
|
||||||
|
err = caddyhttp.Error(http.StatusRequestEntityTooLarge, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Interface guard
|
// Interface guard
|
||||||
var _ caddyhttp.MiddlewareHandler = (*RequestBody)(nil)
|
var _ caddyhttp.MiddlewareHandler = (*RequestBody)(nil)
|
||||||
|
|
|
@ -17,6 +17,7 @@ package caddyhttp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -600,7 +601,8 @@ func PrepareRequest(r *http.Request, repl *caddy.Replacer, w http.ResponseWriter
|
||||||
// If err is a HandlerError, the returned values will
|
// If err is a HandlerError, the returned values will
|
||||||
// have richer information.
|
// have richer information.
|
||||||
func errLogValues(err error) (status int, msg string, fields []zapcore.Field) {
|
func errLogValues(err error) (status int, msg string, fields []zapcore.Field) {
|
||||||
if handlerErr, ok := err.(HandlerError); ok {
|
var handlerErr HandlerError
|
||||||
|
if errors.As(err, &handlerErr) {
|
||||||
status = handlerErr.StatusCode
|
status = handlerErr.StatusCode
|
||||||
if handlerErr.Err == nil {
|
if handlerErr.Err == nil {
|
||||||
msg = err.Error()
|
msg = err.Error()
|
||||||
|
|
Loading…
Reference in a new issue