From: Brad Fitzpatrick Date: Mon, 24 Jun 2013 20:27:56 +0000 (-0700) Subject: net/http: Transport should return an error when response body ends early X-Git-Tag: go1.2rc2~1187 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a054028471d08b5344d5cdb2781259fed84b6f7b;p=gostls13.git net/http: Transport should return an error when response body ends early If a server response contains a Content-Length and the body is short, the Transport should end in io.ErrUnexpectedEOF, not io.EOF. Fixes #5738 R=golang-dev, kevlar, r CC=golang-dev https://golang.org/cl/10237050 --- diff --git a/src/pkg/net/http/response_test.go b/src/pkg/net/http/response_test.go index 02796e88b4..1f44750880 100644 --- a/src/pkg/net/http/response_test.go +++ b/src/pkg/net/http/response_test.go @@ -565,3 +565,29 @@ func TestResponseStatusStutter(t *testing.T) { t.Errorf("stutter in status: %s", buf.String()) } } + +func TestResponseContentLengthShortBody(t *testing.T) { + const shortBody = "Short body, not 123 bytes." + br := bufio.NewReader(strings.NewReader("HTTP/1.1 200 OK\r\n" + + "Content-Length: 123\r\n" + + "\r\n" + + shortBody)) + res, err := ReadResponse(br, &Request{Method: "GET"}) + if err != nil { + t.Fatal(err) + } + if res.ContentLength != 123 { + t.Fatalf("Content-Length = %d; want 123", res.ContentLength) + } + var buf bytes.Buffer + n, err := io.Copy(&buf, res.Body) + if n != int64(len(shortBody)) { + t.Errorf("Copied %d bytes; want %d, len(%q)", n, len(shortBody), shortBody) + } + if buf.String() != shortBody { + t.Errorf("Read body %q; want %q", buf.String(), shortBody) + } + if err != io.ErrUnexpectedEOF { + t.Errorf("io.Copy error = %#v; want io.ErrUnexpectedEOF", err) + } +} diff --git a/src/pkg/net/http/transfer.go b/src/pkg/net/http/transfer.go index b97f7160f4..2b227735a8 100644 --- a/src/pkg/net/http/transfer.go +++ b/src/pkg/net/http/transfer.go @@ -532,13 +532,22 @@ func (b *body) Read(p []byte) (n int, err error) { } n, err = b.Reader.Read(p) - // Read the final trailer once we hit EOF. - if err == io.EOF && b.hdr != nil { - if e := b.readTrailer(); e != nil { - err = e + if err == io.EOF { + // Chunked case. Read the trailer. + if b.hdr != nil { + if e := b.readTrailer(); e != nil { + err = e + } + b.hdr = nil + } else { + // If the server declared the Content-Length, our body is a LimitedReader + // and we need to check whether this EOF arrived early. + if lr, ok := b.Reader.(*io.LimitedReader); ok && lr.N > 0 { + err = io.ErrUnexpectedEOF + } } - b.hdr = nil } + return n, err }