]> Cypherpunks repositories - gostls13.git/commitdiff
http: handle unchunked, un-lengthed HTTP/1.1 responses
authorBrad Fitzpatrick <bradfitz@golang.org>
Wed, 9 Feb 2011 04:35:02 +0000 (20:35 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 9 Feb 2011 04:35:02 +0000 (20:35 -0800)
Fixes #716

This CL simply resumes the previous CL in-flight at
https://golang.org/cl/906042/

R=rsc, petar-m, dsymonds
CC=golang-dev
https://golang.org/cl/4157042

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

index 89a8c3b44d2481886b3fd42d8b526e57d6bb4320..11bfdd08c3ca117aa179468269d8b10fc18a8179 100644 (file)
@@ -44,6 +44,47 @@ var respTests = []respTest{
                "Body here\n",
        },
 
+       // Unchunked HTTP/1.1 response without Content-Length or
+       // Connection headers.
+       {
+               "HTTP/1.1 200 OK\r\n" +
+                       "\r\n" +
+                       "Body here\n",
+
+               Response{
+                       Status:        "200 OK",
+                       StatusCode:    200,
+                       Proto:         "HTTP/1.1",
+                       ProtoMajor:    1,
+                       ProtoMinor:    1,
+                       RequestMethod: "GET",
+                       Close:         true,
+                       ContentLength: -1,
+               },
+
+               "Body here\n",
+       },
+
+       // Unchunked HTTP/1.1 204 response without Content-Length.
+       {
+               "HTTP/1.1 204 No Content\r\n" +
+                       "\r\n" +
+                       "Body should not be read!\n",
+
+               Response{
+                       Status:        "204 No Content",
+                       StatusCode:    204,
+                       Proto:         "HTTP/1.1",
+                       ProtoMajor:    1,
+                       ProtoMinor:    1,
+                       RequestMethod: "GET",
+                       Close:         false,
+                       ContentLength: 0,
+               },
+
+               "",
+       },
+
        // Unchunked response with Content-Length.
        {
                "HTTP/1.0 200 OK\r\n" +
index e62885d62fd5a94e05633e631d30d29908c01a62..f80f0ac63dda9f04120e4c26983d02dc7609c8d1 100644 (file)
@@ -172,6 +172,20 @@ type transferReader struct {
        Trailer          map[string]string
 }
 
+// bodyAllowedForStatus returns whether a given response status code
+// permits a body.  See RFC2616, section 4.4.
+func bodyAllowedForStatus(status int) bool {
+       switch {
+       case status >= 100 && status <= 199:
+               return false
+       case status == 204:
+               return false
+       case status == 304:
+               return false
+       }
+       return true
+}
+
 // msg is *Request or *Response.
 func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
        t := &transferReader{}
@@ -217,6 +231,19 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
                return err
        }
 
+       // If there is no Content-Length or chunked Transfer-Encoding on a *Response
+       // and the status is not 1xx, 204 or 304, then the body is unbounded.
+       // See RFC2616, section 4.4.
+       switch msg.(type) {
+       case *Response:
+               if t.ContentLength == -1 &&
+                       !chunked(t.TransferEncoding) &&
+                       bodyAllowedForStatus(t.StatusCode) {
+                       // Unbounded body.
+                       t.Close = true
+               }
+       }
+
        // Prepare body reader.  ContentLength < 0 means chunked encoding
        // or close connection when finished, since multipart is not supported yet
        switch {