Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 13, 21:45 UTC
requestbody: Return HTTP 413 (fix #4558)
Matthew Holt committed
Mar 11, 2022 at 12:34 UTC
3d616e8c6d65e5617f5a918d72fb1514c9c7144e
4 files changed
+25
-8
modules/caddyhttp/errors.go
+3
@@ -82,6 +82,9 @@ func (e HandlerError) Error() string {
82
return strings.TrimSpace(s)
83
}
84
85
+// Unwrap returns the underlying error value. See the `errors` package for info.
86
+func (e HandlerError) Unwrap() error { return e.Err }
87
+
88
// randString returns a string of n random characters.
89
// It is not even remotely secure OR a proper distribution.
90
// But it's good enough for some things. It excludes certain
modules/caddyhttp/replacer.go
+2
-6
@@ -162,12 +162,8 @@ func addHTTPVarsToReplacer(repl *caddy.Replacer, req *http.Request, w http.Respo
162
// read the request body into a buffer (can't pool because we
163
// don't know its lifetime and would have to make a copy anyway)
164
buf := new(bytes.Buffer)
165
- _, err := io.Copy(buf, req.Body)
166
- if err != nil {
167
- return "", true
168
- }
169
- // replace real body with buffered data
170
- req.Body = io.NopCloser(buf)
165
+ _, _ = io.Copy(buf, req.Body) // can't handle error, so just ignore it
166
+ req.Body = io.NopCloser(buf) // replace real body with buffered data
167
return buf.String(), true
168
169
// original request, before any internal changes
modules/caddyhttp/requestbody/requestbody.go
+17
-1
@@ -15,6 +15,7 @@
15
package requestbody
16
17
import (
18
+ "io"
19
"net/http"
20
21
"github.com/caddyserver/caddy/v2"
@@ -28,6 +29,7 @@ func init() {
29
// RequestBody is a middleware for manipulating the request body.
30
type RequestBody struct {
31
// The maximum number of bytes to allow reading from the body by a later handler.
32
+ // If more bytes are read, an error with HTTP status 413 is returned.
33
MaxSize int64 `json:"max_size,omitempty"`
34
}
35
@@ -44,10 +46,24 @@ func (rb RequestBody) ServeHTTP(w http.ResponseWriter, r *http.Request, next cad
46
return next.ServeHTTP(w, r)
47
}
48
if rb.MaxSize > 0 {
47
- r.Body = http.MaxBytesReader(w, r.Body, rb.MaxSize)
49
+ r.Body = errorWrapper{http.MaxBytesReader(w, r.Body, rb.MaxSize)}
50
}
51
return next.ServeHTTP(w, r)
52
}
53
54
+// errorWrapper wraps errors that are returned from Read()
55
+// so that they can be associated with a proper status code.
56
+type errorWrapper struct {
57
+ io.ReadCloser
58
+}
59
+
60
+func (ew errorWrapper) Read(p []byte) (n int, err error) {
61
+ n, err = ew.ReadCloser.Read(p)
62
+ if err != nil && err.Error() == "http: request body too large" {
63
+ err = caddyhttp.Error(http.StatusRequestEntityTooLarge, err)
64
+ }
65
+ return
66
+}
67
+
68
// Interface guard
69
var _ caddyhttp.MiddlewareHandler = (*RequestBody)(nil)
modules/caddyhttp/server.go
+3
-1
@@ -17,6 +17,7 @@ package caddyhttp
17
import (
18
"context"
19
"encoding/json"
20
+ "errors"
21
"fmt"
22
"net"
23
"net/http"
@@ -600,7 +601,8 @@ func PrepareRequest(r *http.Request, repl *caddy.Replacer, w http.ResponseWriter
601
// If err is a HandlerError, the returned values will
602
// have richer information.
603
func errLogValues(err error) (status int, msg string, fields []zapcore.Field) {
603
- if handlerErr, ok := err.(HandlerError); ok {
604
+ var handlerErr HandlerError
605
+ if errors.As(err, &handlerErr) {
606
status = handlerErr.StatusCode
607
if handlerErr.Err == nil {
608
msg = err.Error()