aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/request.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/http/request.go')
-rw-r--r--src/net/http/request.go36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/net/http/request.go b/src/net/http/request.go
index fe6b60982c..adba5406e9 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -15,7 +15,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"mime"
"mime/multipart"
"net"
@@ -175,6 +174,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
@@ -382,7 +385,7 @@ func (r *Request) Clone(ctx context.Context) *Request {
if s := r.TransferEncoding; s != nil {
s2 := make([]string, len(s))
copy(s2, s)
- r2.TransferEncoding = s
+ r2.TransferEncoding = s2
}
r2.Form = cloneURLValues(r.Form)
r2.PostForm = cloneURLValues(r.PostForm)
@@ -540,6 +543,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 {
@@ -549,6 +553,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.
@@ -667,6 +680,7 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
trace.Wait100Continue()
}
if !waitForContinue() {
+ closed = true
r.closeBody()
return nil
}
@@ -679,6 +693,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 {
@@ -854,7 +869,7 @@ func NewRequestWithContext(ctx context.Context, method, url string, body io.Read
}
rc, ok := body.(io.ReadCloser)
if !ok && body != nil {
- rc = ioutil.NopCloser(body)
+ rc = io.NopCloser(body)
}
// The host's colon:port should be normalized. See Issue 14836.
u.Host = removeEmptyPort(u.Host)
@@ -876,21 +891,21 @@ func NewRequestWithContext(ctx context.Context, method, url string, body io.Read
buf := v.Bytes()
req.GetBody = func() (io.ReadCloser, error) {
r := bytes.NewReader(buf)
- return ioutil.NopCloser(r), nil
+ return io.NopCloser(r), nil
}
case *bytes.Reader:
req.ContentLength = int64(v.Len())
snapshot := *v
req.GetBody = func() (io.ReadCloser, error) {
r := snapshot
- return ioutil.NopCloser(&r), nil
+ return io.NopCloser(&r), nil
}
case *strings.Reader:
req.ContentLength = int64(v.Len())
snapshot := *v
req.GetBody = func() (io.ReadCloser, error) {
r := snapshot
- return ioutil.NopCloser(&r), nil
+ return io.NopCloser(&r), nil
}
default:
// This is where we'd set it to -1 (at least
@@ -1189,7 +1204,7 @@ func parsePostForm(r *Request) (vs url.Values, err error) {
maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
reader = io.LimitReader(r.Body, maxFormSize+1)
}
- b, e := ioutil.ReadAll(reader)
+ b, e := io.ReadAll(reader)
if e != nil {
if err == nil {
err = e
@@ -1383,10 +1398,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 {