]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: add MaxBytesError
authorCarl Johnson <me@carlmjohnson.net>
Mon, 28 Mar 2022 17:02:43 +0000 (17:02 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 25 Apr 2022 23:36:50 +0000 (23:36 +0000)
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>

api/next/30715.txt [new file with mode: 0644]
src/net/http/request.go
src/net/http/serve_test.go

diff --git a/api/next/30715.txt b/api/next/30715.txt
new file mode 100644 (file)
index 0000000..077a8d1
--- /dev/null
@@ -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
index 312211977d55429dc5db6d69c0082e279c3eb8e6..d091f3c056ab0a4116e1ca444a4801cd09d4be6a 100644 (file)
@@ -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
 }
 
index 1c85a665997841c432ea6ce1c55847630d1a7333..404cca0825a85ab1cc1894003fd52dec4b52fa43 100644 (file)
@@ -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()