mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
net/http: refactor testing of Request.Body on 0 ContentLength
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>
This commit is contained in:
parent
ab6ba99484
commit
9491e7d65e
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue