diff options
author | Ross Light <ross@zombiezen.com> | 2020-09-26 08:49:56 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2020-10-16 16:53:27 +0000 |
commit | 606d4a38b9ae76df30cc1bcaeee79923a5792e59 (patch) | |
tree | a4934607d4ad2c49af503a76539ededd69774df0 /src/net/http/request.go | |
parent | dfee3332e66bd3f3afd76615767d2cd9b1905b26 (diff) | |
download | go-606d4a38b9ae76df30cc1bcaeee79923a5792e59.tar.gz go-606d4a38b9ae76df30cc1bcaeee79923a5792e59.zip |
net/http: ensure Request.Body.Close is called once and only once
Makes *Request.write always close the body, so that callers no longer
have to close the body on returned errors, which was the trigger for
double-close behavior.
Fixes #40382
Change-Id: I128f7ec70415f240d82154cfca134b3f692191e3
Reviewed-on: https://go-review.googlesource.com/c/go/+/257819
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Trust: Damien Neil <dneil@google.com>
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/net/http/request.go')
-rw-r--r-- | src/net/http/request.go | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/net/http/request.go b/src/net/http/request.go index 183606d0ff..df73d5f62d 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -544,6 +544,7 @@ var errMissingHost = errors.New("http: Request.Write on Request with no Host or // extraHeaders may be nil // waitForContinue may be nil +// always closes body func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitForContinue func() bool) (err error) { trace := httptrace.ContextClientTrace(r.Context()) if trace != nil && trace.WroteRequest != nil { @@ -553,6 +554,15 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF }) }() } + closed := false + defer func() { + if closed { + return + } + if closeErr := r.closeBody(); closeErr != nil && err == nil { + err = closeErr + } + }() // Find the target host. Prefer the Host: header, but if that // is not given, use the host from the request URL. @@ -671,6 +681,7 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF trace.Wait100Continue() } if !waitForContinue() { + closed = true r.closeBody() return nil } @@ -683,6 +694,7 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF } // Write body and trailer + closed = true err = tw.writeBody(w) if err != nil { if tw.bodyReadError == err { @@ -1387,10 +1399,11 @@ func (r *Request) wantsClose() bool { return hasToken(r.Header.get("Connection"), "close") } -func (r *Request) closeBody() { - if r.Body != nil { - r.Body.Close() +func (r *Request) closeBody() error { + if r.Body == nil { + return nil } + return r.Body.Close() } func (r *Request) isReplayable() bool { |