]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: Transport should return an error when response body ends early
authorBrad Fitzpatrick <bradfitz@golang.org>
Mon, 24 Jun 2013 20:27:56 +0000 (13:27 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Mon, 24 Jun 2013 20:27:56 +0000 (13:27 -0700)
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

src/pkg/net/http/response_test.go
src/pkg/net/http/transfer.go

index 02796e88b4c4453ea2543fb44eebe6efbd486df1..1f4475088054296f2cb4500639486069ae33e49e 100644 (file)
@@ -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)
+       }
+}
index b97f7160f4de9bfd4f7c5d6112e26417063c57e3..2b227735a891af79a5d670019249a3228a2b5c2b 100644 (file)
@@ -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
 }