},
"Your Authentication failed.\r\n",
},
-
- // leading whitespace in the first header. golang.org/issue/22464
- {
- "HTTP/1.1 200 OK\r\n" +
- " Content-type: text/html\r\n" +
- "\tIgnore: foobar\r\n" +
- "Foo: bar\r\n\r\n",
- Response{
- Status: "200 OK",
- StatusCode: 200,
- Proto: "HTTP/1.1",
- ProtoMajor: 1,
- ProtoMinor: 1,
- Request: dummyReq("GET"),
- Header: Header{
- "Foo": {"bar"},
- },
- Close: true,
- ContentLength: -1,
- },
- "",
- },
}
// tests successful calls to ReadResponse, and inspects the returned Response.
type testCase struct {
name string // optional, defaults to in
in string
- header Header
wantErr interface{} // nil, err value, or string substring
}
}
}
- contentLength := func(status, body string, wantErr interface{}, header Header) testCase {
+ contentLength := func(status, body string, wantErr interface{}) testCase {
return testCase{
name: fmt.Sprintf("status %q %q", status, body),
in: fmt.Sprintf("HTTP/1.1 %s\r\n%s", status, body),
wantErr: wantErr,
- header: header,
}
}
errMultiCL := "message cannot contain multiple Content-Length headers"
tests := []testCase{
- {"", "", nil, io.ErrUnexpectedEOF},
- {"", "HTTP/1.1 301 Moved Permanently\r\nFoo: bar", nil, io.ErrUnexpectedEOF},
- {"", "HTTP/1.1", nil, "malformed HTTP response"},
- {"", "HTTP/2.0", nil, "malformed HTTP response"},
+ {"", "", io.ErrUnexpectedEOF},
+ {"", "HTTP/1.1 301 Moved Permanently\r\nFoo: bar", io.ErrUnexpectedEOF},
+ {"", "HTTP/1.1", "malformed HTTP response"},
+ {"", "HTTP/2.0", "malformed HTTP response"},
status("20X Unknown", true),
status("abcd Unknown", true),
status("二百/两百 OK", true),
version("HTTP/1", true),
version("http/1.1", true),
- contentLength("200 OK", "Content-Length: 10\r\nContent-Length: 7\r\n\r\nGopher hey\r\n", errMultiCL, nil),
- contentLength("200 OK", "Content-Length: 7\r\nContent-Length: 7\r\n\r\nGophers\r\n", nil, Header{"Content-Length": {"7"}}),
- contentLength("201 OK", "Content-Length: 0\r\nContent-Length: 7\r\n\r\nGophers\r\n", errMultiCL, nil),
- contentLength("300 OK", "Content-Length: 0\r\nContent-Length: 0 \r\n\r\nGophers\r\n", nil, Header{"Content-Length": {"0"}}),
- contentLength("200 OK", "Content-Length:\r\nContent-Length:\r\n\r\nGophers\r\n", nil, nil),
- contentLength("206 OK", "Content-Length:\r\nContent-Length: 0 \r\nConnection: close\r\n\r\nGophers\r\n", errMultiCL, nil),
+ contentLength("200 OK", "Content-Length: 10\r\nContent-Length: 7\r\n\r\nGopher hey\r\n", errMultiCL),
+ contentLength("200 OK", "Content-Length: 7\r\nContent-Length: 7\r\n\r\nGophers\r\n", nil),
+ contentLength("201 OK", "Content-Length: 0\r\nContent-Length: 7\r\n\r\nGophers\r\n", errMultiCL),
+ contentLength("300 OK", "Content-Length: 0\r\nContent-Length: 0 \r\n\r\nGophers\r\n", nil),
+ contentLength("200 OK", "Content-Length:\r\nContent-Length:\r\n\r\nGophers\r\n", nil),
+ contentLength("206 OK", "Content-Length:\r\nContent-Length: 0 \r\nConnection: close\r\n\r\nGophers\r\n", errMultiCL),
// multiple content-length headers for 204 and 304 should still be checked
- contentLength("204 OK", "Content-Length: 7\r\nContent-Length: 8\r\n\r\n", errMultiCL, nil),
- contentLength("204 OK", "Content-Length: 3\r\nContent-Length: 3\r\n\r\n", nil, nil),
- contentLength("304 OK", "Content-Length: 880\r\nContent-Length: 1\r\n\r\n", errMultiCL, nil),
- contentLength("304 OK", "Content-Length: 961\r\nContent-Length: 961\r\n\r\n", nil, nil),
+ contentLength("204 OK", "Content-Length: 7\r\nContent-Length: 8\r\n\r\n", errMultiCL),
+ contentLength("204 OK", "Content-Length: 3\r\nContent-Length: 3\r\n\r\n", nil),
+ contentLength("304 OK", "Content-Length: 880\r\nContent-Length: 1\r\n\r\n", errMultiCL),
+ contentLength("304 OK", "Content-Length: 961\r\nContent-Length: 961\r\n\r\n", nil),
+
+ // golang.org/issue/22464
+ {"leading space in header", "HTTP/1.1 200 OK\r\n Content-type: text/html\r\nFoo: bar\r\n\r\n", "malformed MIME"},
+ {"leading tab in header", "HTTP/1.1 200 OK\r\n\tContent-type: text/html\r\nFoo: bar\r\n\r\n", "malformed MIME"},
}
for i, tt := range tests {
}
}
-func TestReadMIMEHeaderLeadingSpace(t *testing.T) {
- tests := []struct {
- input string
- want MIMEHeader
- }{
- {" Ignore: ignore\r\nFoo: foo\r\n\r\n", MIMEHeader{"Foo": {"foo"}}},
- {"\tIgnore: ignore\r\nFoo: foo\r\n\r\n", MIMEHeader{"Foo": {"foo"}}},
- {" Ignore1: ignore\r\n Ignore2: ignore\r\nFoo: foo\r\n\r\n", MIMEHeader{"Foo": {"foo"}}},
- {" Ignore1: ignore\r\n\r\n", MIMEHeader{}},
- }
- for _, tt := range tests {
- r := reader(tt.input)
- m, err := r.ReadMIMEHeader()
- if !reflect.DeepEqual(m, tt.want) || err != nil {
- t.Errorf("ReadMIMEHeader(%q) = %v, %v; want %v", tt.input, m, err, tt.want)
+func TestReadMIMEHeaderMalformed(t *testing.T) {
+ inputs := []string{
+ "No colon first line\r\nFoo: foo\r\n\r\n",
+ " No colon first line with leading space\r\nFoo: foo\r\n\r\n",
+ "\tNo colon first line with leading tab\r\nFoo: foo\r\n\r\n",
+ " First: line with leading space\r\nFoo: foo\r\n\r\n",
+ "\tFirst: line with leading tab\r\nFoo: foo\r\n\r\n",
+ "Foo: foo\r\nNo colon second line\r\n\r\n",
+ }
+
+ for _, input := range inputs {
+ r := reader(input)
+ if m, err := r.ReadMIMEHeader(); err == nil {
+ t.Errorf("ReadMIMEHeader(%q) = %v, %v; want nil, err", input, m, err)
}
}
}