Commit 2aaabfc8 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

http: handle unchunked, un-lengthed HTTP/1.1 responses

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
parent 3629d723
...@@ -44,6 +44,47 @@ var respTests = []respTest{ ...@@ -44,6 +44,47 @@ var respTests = []respTest{
"Body here\n", "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. // Unchunked response with Content-Length.
{ {
"HTTP/1.0 200 OK\r\n" + "HTTP/1.0 200 OK\r\n" +
......
...@@ -172,6 +172,20 @@ type transferReader struct { ...@@ -172,6 +172,20 @@ type transferReader struct {
Trailer map[string]string 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. // msg is *Request or *Response.
func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) { func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
t := &transferReader{} t := &transferReader{}
...@@ -217,6 +231,19 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) { ...@@ -217,6 +231,19 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
return err 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 // Prepare body reader. ContentLength < 0 means chunked encoding
// or close connection when finished, since multipart is not supported yet // or close connection when finished, since multipart is not supported yet
switch { switch {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment