diff options
Diffstat (limited to 'src/net/http/server.go')
| -rw-r--r-- | src/net/http/server.go | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/src/net/http/server.go b/src/net/http/server.go index 02554d1a20..5d8e576f71 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1077,9 +1077,6 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) { req.ctx = ctx req.RemoteAddr = c.remoteAddr req.TLS = c.tlsState - if body, ok := req.Body.(*body); ok { - body.doEarlyClose = true - } // Adjust the read deadline if necessary. if !hdrDeadline.Equal(wholeReqDeadline) { @@ -1711,9 +1708,11 @@ func (w *response) finishRequest() { w.conn.r.abortPendingRead() - // Close the body (regardless of w.closeAfterReply) so we can - // re-use its bufio.Reader later safely. - w.reqBody.Close() + // Try to discard the body (regardless of w.closeAfterReply), so we can + // potentially reuse it in the same connection. + if b, ok := w.reqBody.(*body); ok { + b.tryDiscardBody() + } if w.req.MultipartForm != nil { w.req.MultipartForm.RemoveAll() @@ -1741,16 +1740,16 @@ func (w *response) shouldReuseConnection() bool { return false } - if w.closedRequestBodyEarly() { + if w.didIncompleteDiscard() { return false } return true } -func (w *response) closedRequestBodyEarly() bool { +func (w *response) didIncompleteDiscard() bool { body, ok := w.req.Body.(*body) - return ok && body.didEarlyClose() + return ok && body.didIncompleteDiscard() } func (w *response) Flush() { @@ -2106,6 +2105,18 @@ func (c *conn) serve(ctx context.Context) { // But we're not going to implement HTTP pipelining because it // was never deployed in the wild and the answer is HTTP/2. inFlightResponse = w + // Ensure that Close() invocations within request handlers do not + // discard the body. + if b, ok := w.reqBody.(*body); ok { + b.mu.Lock() + b.inRequestHandler = true + b.mu.Unlock() + defer func() { + b.mu.Lock() + b.inRequestHandler = false + b.mu.Unlock() + }() + } serverHandler{c.server}.ServeHTTP(w, w.req) inFlightResponse = nil w.cancelCtx() @@ -2116,7 +2127,7 @@ func (c *conn) serve(ctx context.Context) { w.finishRequest() c.rwc.SetWriteDeadline(time.Time{}) if !w.shouldReuseConnection() { - if w.requestBodyLimitHit || w.closedRequestBodyEarly() { + if w.requestBodyLimitHit || w.didIncompleteDiscard() { c.closeWriteAndWait() } return |
