aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/request.go
diff options
context:
space:
mode:
authorRoss Light <ross@zombiezen.com>2020-09-26 08:49:56 -0700
committerRuss Cox <rsc@golang.org>2020-10-16 16:53:27 +0000
commit606d4a38b9ae76df30cc1bcaeee79923a5792e59 (patch)
treea4934607d4ad2c49af503a76539ededd69774df0 /src/net/http/request.go
parentdfee3332e66bd3f3afd76615767d2cd9b1905b26 (diff)
downloadgo-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.go19
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 {