Return ErrResponseTooLarge instead of truncating response body
WithMaxResponseBody wrapped the body in io.LimitedReader, which returns EOF at the cap, so Bytes/JSON/XML silently returned a truncated body with a nil error despite the documented contract. Read one byte past the limit and return the new ErrResponseTooLarge sentinel when exceeded; bodies exactly at the limit still succeed.
This commit is contained in:
21
response.go
21
response.go
@@ -98,17 +98,26 @@ func (r *Response) BodyReader() io.Reader {
|
||||
return r.Body
|
||||
}
|
||||
|
||||
// limitedReadCloser wraps an io.LimitedReader with a separate Closer
|
||||
// so the original body can be closed.
|
||||
// limitedReadCloser enforces a maximum number of bytes that may be read from
|
||||
// a response body. Reading more than limit bytes returns ErrResponseTooLarge
|
||||
// rather than silently truncating the body. The original body is closed via
|
||||
// the separate Closer.
|
||||
type limitedReadCloser struct {
|
||||
R io.LimitedReader
|
||||
C io.Closer
|
||||
r io.Reader // an io.LimitReader over the original body (limit+1 bytes)
|
||||
c io.Closer // the original body, for Close
|
||||
limit int64
|
||||
read int64
|
||||
}
|
||||
|
||||
func (l *limitedReadCloser) Read(p []byte) (int, error) {
|
||||
return l.R.Read(p)
|
||||
n, err := l.r.Read(p)
|
||||
l.read += int64(n)
|
||||
if l.read > l.limit {
|
||||
return n, ErrResponseTooLarge
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (l *limitedReadCloser) Close() error {
|
||||
return l.C.Close()
|
||||
return l.c.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user