Skip to content

Commit a5d61be

Browse files
earthboundkidgopherbot
authored andcommitted
net/http: add MaxBytesError
Fixes #30715 Change-Id: Ia3712d248b6dc86abef71ccea6e705a571933d53 GitHub-Last-Rev: 6ae6840 GitHub-Pull-Request: #49359 Reviewed-on: https://go-review.googlesource.com/c/go/+/361397 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 892cd0b commit a5d61be

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

api/next/30715.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pkg net/http, type MaxBytesError struct #30715
2+
pkg net/http, type MaxBytesError struct, Limit int64 #30715
3+
pkg net/http, method (*MaxBytesError) Error() string #30715

src/net/http/request.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,21 +1126,34 @@ func readRequest(b *bufio.Reader) (req *Request, err error) {
11261126
// MaxBytesReader is similar to io.LimitReader but is intended for
11271127
// limiting the size of incoming request bodies. In contrast to
11281128
// io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a
1129-
// non-EOF error for a Read beyond the limit, and closes the
1129+
// MaxBytesError for a Read beyond the limit, and closes the
11301130
// underlying reader when its Close method is called.
11311131
//
11321132
// MaxBytesReader prevents clients from accidentally or maliciously
1133-
// sending a large request and wasting server resources.
1133+
// sending a large request and wasting server resources. If possible,
1134+
// it tells the ResponseWriter to close the connection after the limit
1135+
// has been reached.
11341136
func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
11351137
if n < 0 { // Treat negative limits as equivalent to 0.
11361138
n = 0
11371139
}
1138-
return &maxBytesReader{w: w, r: r, n: n}
1140+
return &maxBytesReader{w: w, r: r, i: n, n: n}
1141+
}
1142+
1143+
// MaxBytesError is returned by MaxBytesReader when its read limit is exceeded.
1144+
type MaxBytesError struct {
1145+
Limit int64
1146+
}
1147+
1148+
func (e *MaxBytesError) Error() string {
1149+
// Due to Hyrum's law, this text cannot be changed.
1150+
return "http: request body too large"
11391151
}
11401152

11411153
type maxBytesReader struct {
11421154
w ResponseWriter
11431155
r io.ReadCloser // underlying reader
1156+
i int64 // max bytes initially, for MaxBytesError
11441157
n int64 // max bytes remaining
11451158
err error // sticky error
11461159
}
@@ -1182,7 +1195,7 @@ func (l *maxBytesReader) Read(p []byte) (n int, err error) {
11821195
if res, ok := l.w.(requestTooLarger); ok {
11831196
res.requestTooLarge()
11841197
}
1185-
l.err = errors.New("http: request body too large")
1198+
l.err = &MaxBytesError{l.i}
11861199
return n, l.err
11871200
}
11881201

src/net/http/serve_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,13 @@ func testRequestBodyLimit(t *testing.T, h2 bool) {
30353035
if n != limit {
30363036
t.Errorf("io.Copy = %d, want %d", n, limit)
30373037
}
3038+
mbErr, ok := err.(*MaxBytesError)
3039+
if !ok {
3040+
t.Errorf("expected MaxBytesError, got %T", err)
3041+
}
3042+
if mbErr.Limit != limit {
3043+
t.Errorf("MaxBytesError.Limit = %d, want %d", mbErr.Limit, limit)
3044+
}
30383045
}))
30393046
defer cst.close()
30403047

0 commit comments

Comments
 (0)