net/http: document concurrency expectations for Request.Body

This is primarily aimed at client requests where the user can supply
their own io.ReadCloser, but also clarifies server request behavior.
A server request body can be one of:

- *body
- *http2RequestBody
- *expectContinueReader
- *maxBytesReader

Of those, *expectContinueReader did not meet these expectations, so this
change also removes the data race.

Change-Id: Id4f1ae573d938347b1123a7b612b271aabb045a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/251087
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Trust: Damien Neil <dneil@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
Ross Light 2020-08-27 13:08:29 -07:00 committed by Russ Cox
parent c06a699fb6
commit dfee3332e6
2 changed files with 7 additions and 3 deletions

View File

@ -175,6 +175,10 @@ type Request struct {
// but will return EOF immediately when no body is present.
// The Server will close the request body. The ServeHTTP
// Handler does not need to.
//
// Body must allow Read to be called concurrently with Close.
// In particular, calling Close should unblock a Read waiting
// for input.
Body io.ReadCloser
// GetBody defines an optional func to return a new copy of

View File

@ -890,12 +890,12 @@ func (srv *Server) initialReadLimitSize() int64 {
type expectContinueReader struct {
resp *response
readCloser io.ReadCloser
closed bool
closed atomicBool
sawEOF atomicBool
}
func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
if ecr.closed {
if ecr.closed.isSet() {
return 0, ErrBodyReadAfterClose
}
w := ecr.resp
@ -917,7 +917,7 @@ func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
}
func (ecr *expectContinueReader) Close() error {
ecr.closed = true
ecr.closed.setTrue()
return ecr.readCloser.Close()
}