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

net/http: ignore Transfer-Encoding for HTTP/1.0 responses

Fixes #12785

Change-Id: Iae4383889298c6a78b1ba41bd2cda70b0758fcba
Reviewed-on: https://go-review.googlesource.com/15737Reviewed-by: 's avatarAndrew Gerrand <adg@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 2961cab9
...@@ -456,6 +456,55 @@ some body`, ...@@ -456,6 +456,55 @@ some body`,
"", "",
}, },
// Issue 12785: HTTP/1.0 response with bogus (to be ignored) Transfer-Encoding.
// Without a Content-Length.
{
"HTTP/1.0 200 OK\r\n" +
"Transfer-Encoding: bogus\r\n" +
"\r\n" +
"Body here\n",
Response{
Status: "200 OK",
StatusCode: 200,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Request: dummyReq("GET"),
Header: Header{},
Close: true,
ContentLength: -1,
},
"Body here\n",
},
// Issue 12785: HTTP/1.0 response with bogus (to be ignored) Transfer-Encoding.
// With a Content-Length.
{
"HTTP/1.0 200 OK\r\n" +
"Transfer-Encoding: bogus\r\n" +
"Content-Length: 10\r\n" +
"\r\n" +
"Body here\n",
Response{
Status: "200 OK",
StatusCode: 200,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Request: dummyReq("GET"),
Header: Header{
"Content-Length": {"10"},
},
Close: true,
ContentLength: 10,
},
"Body here\n",
},
} }
func TestReadResponse(t *testing.T) { func TestReadResponse(t *testing.T) {
......
...@@ -271,6 +271,10 @@ type transferReader struct { ...@@ -271,6 +271,10 @@ type transferReader struct {
Trailer Header Trailer Header
} }
func (t *transferReader) protoAtLeast(m, n int) bool {
return t.ProtoMajor > m || (t.ProtoMajor == m && t.ProtoMinor >= n)
}
// bodyAllowedForStatus reports whether a given response status code // bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC2616, section 4.4. // permits a body. See RFC2616, section 4.4.
func bodyAllowedForStatus(status int) bool { func bodyAllowedForStatus(status int) bool {
...@@ -337,7 +341,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) { ...@@ -337,7 +341,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
} }
// Transfer encoding, content length // Transfer encoding, content length
t.TransferEncoding, err = fixTransferEncoding(isResponse, t.RequestMethod, t.Header) err = t.fixTransferEncoding()
if err != nil { if err != nil {
return err return err
} }
...@@ -424,13 +428,18 @@ func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" } ...@@ -424,13 +428,18 @@ func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
// Checks whether the encoding is explicitly "identity". // Checks whether the encoding is explicitly "identity".
func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" } func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
// Sanitize transfer encoding // fixTransferEncoding sanitizes t.TransferEncoding, if needed.
func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ([]string, error) { func (t *transferReader) fixTransferEncoding() error {
raw, present := header["Transfer-Encoding"] raw, present := t.Header["Transfer-Encoding"]
if !present { if !present {
return nil, nil return nil
}
delete(t.Header, "Transfer-Encoding")
// Issue 12785; ignore Transfer-Encoding on HTTP/1.0 requests.
if !t.protoAtLeast(1, 1) {
return nil
} }
delete(header, "Transfer-Encoding")
encodings := strings.Split(raw[0], ",") encodings := strings.Split(raw[0], ",")
te := make([]string, 0, len(encodings)) te := make([]string, 0, len(encodings))
...@@ -445,13 +454,13 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ( ...@@ -445,13 +454,13 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
break break
} }
if encoding != "chunked" { if encoding != "chunked" {
return nil, &badStringError{"unsupported transfer encoding", encoding} return &badStringError{"unsupported transfer encoding", encoding}
} }
te = te[0 : len(te)+1] te = te[0 : len(te)+1]
te[len(te)-1] = encoding te[len(te)-1] = encoding
} }
if len(te) > 1 { if len(te) > 1 {
return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")} return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
} }
if len(te) > 0 { if len(te) > 0 {
// RFC 7230 3.3.2 says "A sender MUST NOT send a // RFC 7230 3.3.2 says "A sender MUST NOT send a
...@@ -470,11 +479,12 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ( ...@@ -470,11 +479,12 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
// such a message downstream." // such a message downstream."
// //
// Reportedly, these appear in the wild. // Reportedly, these appear in the wild.
delete(header, "Content-Length") delete(t.Header, "Content-Length")
return te, nil t.TransferEncoding = te
return nil
} }
return nil, nil return nil
} }
// Determine the expected body length, using RFC 2616 Section 4.4. This // Determine the expected body length, using RFC 2616 Section 4.4. This
......
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