Skip to content

net/textproto: CanonicalMIMEHeaderKey ignores keys with _ in #13767

Description

@ncw

textproto.CanonicalMIMEHeaderKey ignores keys with _ in. If an htttp server returns one of these, then it isn't possible to use http.Header.Get to fetch it as it doesn't get canonicalized.

For example, Backblaze use keys with _ in to store metadata - see the X-Bz-Info-src_last_modified_millis in the upload docs.

The Backblaze server returns this header all in lower case. Because it doesn't get canonicalised by textproto.CanonicalMIMEHeaderKey it remains in lower case and consequently `resp.Header.Get("X-Bz-Info-src_last_modified_millis") doesn't find it.

This is easy enough to work around, but caused me a bit of suprise and debugging!

The comment on textproto/reader.go on validHeaderFieldByte explains the problem nicely!

// validHeaderFieldByte reports whether b is a valid byte in a header
// field key. This is actually stricter than RFC 7230, which says:
//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
//           "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
//   token = 1*tchar
// TODO: revisit in Go 1.6+ and possibly expand this. But note that many
// servers have historically dropped '_' to prevent ambiguities when mapping
// to CGI environment variables.
func validHeaderFieldByte(b byte) bool {
    return ('A' <= b && b <= 'Z') ||
        ('a' <= b && b <= 'z') ||
        ('0' <= b && b <= '9') ||
        b == '-'
}

This could cause problems with S3 also which uses a similar scheme for returning user defined metadata too.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions