aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/client.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/http/client.go')
-rw-r--r--src/net/http/client.go15
1 files changed, 14 insertions, 1 deletions
diff --git a/src/net/http/client.go b/src/net/http/client.go
index 638ff500a4..3860d97d8f 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -269,7 +269,20 @@ func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, d
return nil, didTimeout, fmt.Errorf("http: RoundTripper implementation (%T) returned a nil *Response with a nil error", rt)
}
if resp.Body == nil {
- return nil, didTimeout, fmt.Errorf("http: RoundTripper implementation (%T) returned a *Response with a nil Body", rt)
+ // The documentation on the Body field says “The http Client and Transport
+ // guarantee that Body is always non-nil, even on responses without a body
+ // or responses with a zero-length body.” Unfortunately, we didn't document
+ // that same constraint for arbitrary RoundTripper implementations, and
+ // RoundTripper implementations in the wild (mostly in tests) assume that
+ // they can use a nil Body to mean an empty one (similar to Request.Body).
+ // (See https://golang.org/issue/38095.)
+ //
+ // If the ContentLength allows the Body to be empty, fill in an empty one
+ // here to ensure that it is non-nil.
+ if resp.ContentLength > 0 && req.Method != "HEAD" {
+ return nil, didTimeout, fmt.Errorf("http: RoundTripper implementation (%T) returned a *Response with content length %d but a nil Body", rt, resp.ContentLength)
+ }
+ resp.Body = ioutil.NopCloser(strings.NewReader(""))
}
if !deadline.IsZero() {
resp.Body = &cancelTimerBody{