diff options
author | Carl Johnson <me@carlmjohnson.net> | 2022-03-28 17:02:43 +0000 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2022-04-25 23:36:50 +0000 |
commit | a5d61be040ed20b5774bff1b6b578c6d393ab332 (patch) | |
tree | 1a52f1772e17fd02c9da4d7d7d279d76ed472d62 | |
parent | 892cd0b63638ec856e6fef1bdaaa20a177695fea (diff) | |
download | go-a5d61be040ed20b5774bff1b6b578c6d393ab332.tar.gz go-a5d61be040ed20b5774bff1b6b578c6d393ab332.zip |
net/http: add MaxBytesError
Fixes #30715
Change-Id: Ia3712d248b6dc86abef71ccea6e705a571933d53
GitHub-Last-Rev: 6ae68402a5a7c57f7f18e945d48c69ba2b134078
GitHub-Pull-Request: golang/go#49359
Reviewed-on: https://go-review.googlesource.com/c/go/+/361397
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
-rw-r--r-- | api/next/30715.txt | 3 | ||||
-rw-r--r-- | src/net/http/request.go | 21 | ||||
-rw-r--r-- | src/net/http/serve_test.go | 7 |
3 files changed, 27 insertions, 4 deletions
diff --git a/api/next/30715.txt b/api/next/30715.txt new file mode 100644 index 0000000000..077a8d136f --- /dev/null +++ b/api/next/30715.txt @@ -0,0 +1,3 @@ +pkg net/http, type MaxBytesError struct #30715 +pkg net/http, type MaxBytesError struct, Limit int64 #30715 +pkg net/http, method (*MaxBytesError) Error() string #30715 diff --git a/src/net/http/request.go b/src/net/http/request.go index 312211977d..d091f3c056 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -1126,21 +1126,34 @@ func readRequest(b *bufio.Reader) (req *Request, err error) { // MaxBytesReader is similar to io.LimitReader but is intended for // limiting the size of incoming request bodies. In contrast to // io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a -// non-EOF error for a Read beyond the limit, and closes the +// MaxBytesError for a Read beyond the limit, and closes the // underlying reader when its Close method is called. // // MaxBytesReader prevents clients from accidentally or maliciously -// sending a large request and wasting server resources. +// sending a large request and wasting server resources. If possible, +// it tells the ResponseWriter to close the connection after the limit +// has been reached. func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser { if n < 0 { // Treat negative limits as equivalent to 0. n = 0 } - return &maxBytesReader{w: w, r: r, n: n} + return &maxBytesReader{w: w, r: r, i: n, n: n} +} + +// MaxBytesError is returned by MaxBytesReader when its read limit is exceeded. +type MaxBytesError struct { + Limit int64 +} + +func (e *MaxBytesError) Error() string { + // Due to Hyrum's law, this text cannot be changed. + return "http: request body too large" } type maxBytesReader struct { w ResponseWriter r io.ReadCloser // underlying reader + i int64 // max bytes initially, for MaxBytesError n int64 // max bytes remaining err error // sticky error } @@ -1182,7 +1195,7 @@ func (l *maxBytesReader) Read(p []byte) (n int, err error) { if res, ok := l.w.(requestTooLarger); ok { res.requestTooLarge() } - l.err = errors.New("http: request body too large") + l.err = &MaxBytesError{l.i} return n, l.err } diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 1c85a66599..404cca0825 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -3035,6 +3035,13 @@ func testRequestBodyLimit(t *testing.T, h2 bool) { if n != limit { t.Errorf("io.Copy = %d, want %d", n, limit) } + mbErr, ok := err.(*MaxBytesError) + if !ok { + t.Errorf("expected MaxBytesError, got %T", err) + } + if mbErr.Limit != limit { + t.Errorf("MaxBytesError.Limit = %d, want %d", mbErr.Limit, limit) + } })) defer cst.close() |