]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: refactor testing of Request.Body on 0 ContentLength
authorBrad Fitzpatrick <bradfitz@golang.org>
Fri, 30 Sep 2016 17:40:58 +0000 (10:40 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 30 Sep 2016 19:45:34 +0000 (19:45 +0000)
Code movement only, to look more like the equivalent http2 code, and
to make an upcoming fix look more obvious.

Updates #16002 (to be fixed once this code is in)

Change-Id: Iaa4f965be14e98f9996e7c4624afe6e19bed1a80
Reviewed-on: https://go-review.googlesource.com/30087
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
src/net/http/request.go
src/net/http/transfer.go

index b191d519f2a14661adc0808c27c931de80ded9d8..21e25b08efec40d461f69232ec9f1159d993a600 100644 (file)
@@ -1215,3 +1215,42 @@ func (r *Request) isReplayable() bool {
        }
        return false
 }
+
+// bodyAndLength reports the request's body and content length, with
+// the difference from r.ContentLength being that 0 means actually
+// zero, and -1 means unknown.
+func (r *Request) bodyAndLength() (body io.Reader, contentLen int64) {
+       body = r.Body
+       if body == nil {
+               return nil, 0
+       }
+       if r.ContentLength != 0 {
+               return body, r.ContentLength
+       }
+       // Don't try to sniff the bytes if they're using a custom
+       // transfer encoding (or specified chunked themselves), and
+       // don't sniff if they're not using HTTP/1.1 and can't chunk
+       // anyway.
+       if len(r.TransferEncoding) != 0 || !r.ProtoAtLeast(1, 1) {
+               return body, -1
+       }
+
+       // Test to see if it's actually zero or just unset.
+       var buf [1]byte
+       n, err := io.ReadFull(body, buf[:])
+       if err != nil && err != io.EOF {
+               return errorReader{err}, -1
+       }
+
+       if n == 1 {
+               // Oh, guess there is data in this Body Reader after all.
+               // The ContentLength field just wasn't set.
+               // Stich the Body back together again, re-attaching our
+               // consumed byte.
+               // TODO(bradfitz): switch to stitchByteAndReader
+               return io.MultiReader(bytes.NewReader(buf[:]), body), -1
+       }
+
+       // Body is actually empty.
+       return nil, 0
+}
index 851469ccbce16490e0e4c74f478fa10ba36078b4..9d31b71f32f2beab3b36152736d445741567ef3f 100644 (file)
@@ -59,37 +59,17 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
                        return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
                }
                t.Method = valueOrDefault(rr.Method, "GET")
-               t.Body = rr.Body
-               t.BodyCloser = rr.Body
-               t.ContentLength = rr.ContentLength
                t.Close = rr.Close
                t.TransferEncoding = rr.TransferEncoding
                t.Trailer = rr.Trailer
                atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
-               if t.Body != nil && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
-                       if t.ContentLength == 0 {
-                               // Test to see if it's actually zero or just unset.
-                               var buf [1]byte
-                               n, rerr := io.ReadFull(t.Body, buf[:])
-                               if rerr != nil && rerr != io.EOF {
-                                       t.ContentLength = -1
-                                       t.Body = errorReader{rerr}
-                               } else if n == 1 {
-                                       // Oh, guess there is data in this Body Reader after all.
-                                       // The ContentLength field just wasn't set.
-                                       // Stich the Body back together again, re-attaching our
-                                       // consumed byte.
-                                       t.ContentLength = -1
-                                       t.Body = io.MultiReader(bytes.NewReader(buf[:]), t.Body)
-                               } else {
-                                       // Body is actually empty.
-                                       t.Body = nil
-                                       t.BodyCloser = nil
-                               }
-                       }
-                       if t.ContentLength < 0 {
-                               t.TransferEncoding = []string{"chunked"}
-                       }
+
+               t.Body, t.ContentLength = rr.bodyAndLength()
+               if t.Body != nil {
+                       t.BodyCloser = rr.Body
+               }
+               if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
+                       t.TransferEncoding = []string{"chunked"}
                }
        case *Response:
                t.IsResponse = true