Skip to content

Commit 4bc7b5a

Browse files
committed
net/http: revert change making NewRequest set ContentLength -1
The introduction of NoBody and related body-peeking bug fixes also added a "cleanup" of sorts to make NewRequest set the returned Requests's ContentLength to -1 when it didn't know it. Using -1 to mean unknown is what the documentation says, but then people apparently(?) depended on it being zero so they could do this: req, _ := http.NewRequest("POST", url, someNonNilReaderWithUnkownSize) req.Body = nil res, err := http.DefaultClient.Do(req) ... and expect it to work. After https://golang.org/cl/31445 the contrived(?) code above stopped working, since Body was nil and ContentLength was -1, which has been disallowed since Go 1.0. So this restores the old behavior of NewRequest, not setting it to -1. That part of the fix isn't required as of https://golang.org/cl/31726 (which added NoBody) I still don't know whether this bug is hypothetical or actually affected people in practice. Let's assume it's real for now. Fixes #18117 Change-Id: I42400856ee92a1a4999b5b4668bef97d885fbb53 Reviewed-on: https://go-review.googlesource.com/33801 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 7736cba commit 4bc7b5a

File tree

3 files changed

+20
-25
lines changed

3 files changed

+20
-25
lines changed

src/net/http/request.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -785,9 +785,11 @@ func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
785785
return ioutil.NopCloser(&r), nil
786786
}
787787
default:
788-
if body != NoBody {
789-
req.ContentLength = -1 // unknown
790-
}
788+
// This is where we'd set it to -1 (at least
789+
// if body != NoBody) to mean unknown, but
790+
// that broke people during the Go 1.8 testing
791+
// period. People depend on it being 0 I
792+
// guess. Maybe retry later. See Issue 18117.
791793
}
792794
// For client requests, Request.ContentLength of 0
793795
// means either actually 0, or unknown. The only way
@@ -797,7 +799,7 @@ func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
797799
// so we use a well-known ReadCloser variable instead
798800
// and have the http package also treat that sentinel
799801
// variable to mean explicitly zero.
800-
if req.ContentLength == 0 {
802+
if req.GetBody != nil && req.ContentLength == 0 {
801803
req.Body = NoBody
802804
req.GetBody = func() (io.ReadCloser, error) { return NoBody, nil }
803805
}

src/net/http/request_test.go

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -498,10 +498,14 @@ func TestNewRequestContentLength(t *testing.T) {
498498
{bytes.NewBuffer([]byte("1234")), 4},
499499
{strings.NewReader("12345"), 5},
500500
{strings.NewReader(""), 0},
501-
// Not detected:
502-
{struct{ io.Reader }{strings.NewReader("xyz")}, -1},
503-
{io.NewSectionReader(strings.NewReader("x"), 0, 6), -1},
504-
{readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), -1},
501+
{NoBody, 0},
502+
503+
// Not detected. During Go 1.8 we tried to make these set to -1, but
504+
// due to Issue 18117, we keep these returning 0, even though they're
505+
// unknown.
506+
{struct{ io.Reader }{strings.NewReader("xyz")}, 0},
507+
{io.NewSectionReader(strings.NewReader("x"), 0, 6), 0},
508+
{readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), 0},
505509
}
506510
for i, tt := range tests {
507511
req, err := NewRequest("POST", "http://localhost/", tt.r)
@@ -511,9 +515,6 @@ func TestNewRequestContentLength(t *testing.T) {
511515
if req.ContentLength != tt.want {
512516
t.Errorf("test[%d]: ContentLength(%T) = %d; want %d", i, tt.r, req.ContentLength, tt.want)
513517
}
514-
if (req.ContentLength == 0) != (req.Body == NoBody) {
515-
t.Errorf("test[%d]: ContentLength = %d but Body non-nil is %v", i, req.ContentLength, req.Body != nil)
516-
}
517518
}
518519
}
519520

@@ -825,16 +826,6 @@ func TestNewRequestGetBody(t *testing.T) {
825826
}
826827
}
827828

828-
func TestNewRequestNoBody(t *testing.T) {
829-
req, err := NewRequest("GET", "http://foo.com/", NoBody)
830-
if err != nil {
831-
t.Fatal(err)
832-
}
833-
if req.ContentLength != 0 {
834-
t.Errorf("ContentLength = %d; want 0", req.ContentLength)
835-
}
836-
}
837-
838829
func testMissingFile(t *testing.T, req *Request) {
839830
f, fh, err := req.FormFile("missing")
840831
if f != nil {

src/net/http/requestwrite_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,12 +581,14 @@ func (rc *closeChecker) Close() error {
581581
// inside a NopCloser, and that it serializes it correctly.
582582
func TestRequestWriteClosesBody(t *testing.T) {
583583
rc := &closeChecker{Reader: strings.NewReader("my body")}
584-
req, _ := NewRequest("POST", "http://foo.com/", rc)
585-
if req.ContentLength != -1 {
586-
t.Errorf("got req.ContentLength %d, want -1", req.ContentLength)
584+
req, err := NewRequest("POST", "http://foo.com/", rc)
585+
if err != nil {
586+
t.Fatal(err)
587587
}
588588
buf := new(bytes.Buffer)
589-
req.Write(buf)
589+
if err := req.Write(buf); err != nil {
590+
t.Error(err)
591+
}
590592
if !rc.closed {
591593
t.Error("body not closed after write")
592594
}

0 commit comments

Comments
 (0)