// Key ends at first colon; must not have spaces.
i := bytes.IndexByte(kv, ':')
- if i < 0 || bytes.IndexByte(kv[0:i], ' ') >= 0 {
+ if i < 0 {
return m, ProtocolError("malformed MIME header line: " + string(kv))
}
- key := CanonicalMIMEHeaderKey(string(kv[0:i]))
+ key := string(kv[0:i])
+ if strings.Index(key, " ") >= 0 {
+ key = strings.TrimRight(key, " ")
+ }
+ key = CanonicalMIMEHeaderKey(key)
// Skip initial spaces in value.
i++ // skip colon
a := []byte(s)
upper := true
for i, v := range a {
+ if v == ' ' {
+ a[i] = '-'
+ upper = true
+ continue
+ }
if upper && 'a' <= v && v <= 'z' {
a[i] = v + 'A' - 'a'
}
}
}
+// Test that we read slightly-bogus MIME headers seen in the wild,
+// with spaces before colons, and spaces in keys.
+func TestReadMIMEHeaderNonCompliant(t *testing.T) {
+ // Invalid HTTP response header as sent by an Axis security
+ // camera: (this is handled by IE, Firefox, Chrome, curl, etc.)
+ r := reader("Foo: bar\r\n" +
+ "Content-Language: en\r\n" +
+ "SID : 0\r\n" +
+ "Audio Mode : None\r\n" +
+ "Privilege : 127\r\n\r\n")
+ m, err := r.ReadMIMEHeader()
+ want := MIMEHeader{
+ "Foo": {"bar"},
+ "Content-Language": {"en"},
+ "Sid": {"0"},
+ "Audio-Mode": {"None"},
+ "Privilege": {"127"},
+ }
+ if !reflect.DeepEqual(m, want) || err != nil {
+ t.Fatalf("ReadMIMEHeader =\n%v, %v; want:\n%v", m, err, want)
+ }
+}
+
type readResponseTest struct {
in string
inCode int