HTTP request multiple-value header parsing behaviour

926 views
Skip to first unread message

Julian Cooper

unread,
Apr 14, 2015, 6:15:33 PM4/14/15
to golan...@googlegroups.com
When handling inbound requests, I'm noticing that requests with multiple values for a single header are being treated as single value in the http.Request's Header property.

Current behaviour for the following function.
func foo(responseWriter http.ResponseWriter, request *http.Request) {
 
Log.Debug("Accept header: %v. Length: %v", request.Header["Accept"])
 fmt
.Fprintf(responseWriter, "\n")
}

Request with two "Accept" header lines:
$ curl -H "Accept:application/json" -H "Accept:text/plain" localhost:8080/foo -vvv
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /foo HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept:application/json
> Accept:text/plain
>

Output is a slice with two entries:
Accept header: [application/json text/plain]. Length: 2

Request with a single "Accept" header line containing multiple comma-separated values. I would hope that its behaviour would be identical to above, but instead it is treated as one value:
$ curl -H "Accept: application/json, text/plain" localhost:8080/foo -vvv
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /foo HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: application/json, text/plain
>

Output:
Accept header: [application/json, text/plain]. Length: 1

Having to handle these two functionally identical requests differently depending on how a client formats its requests is ugly in my opinion . Am I doing something wrong?

Ian Davis

unread,
Apr 14, 2015, 7:44:17 PM4/14/15
to golan...@googlegroups.com
On Tue, Apr 14, 2015, at 11:15 PM, Julian Cooper wrote:
When handling inbound requests, I'm noticing that requests with multiple values for a single header are being treated as single value in the http.Request's Header property.
 
Both requests give you a slice. The behaviour is the same.
 
If you want a single slice of acceptable media types then just join the slices: strings.Join(request.Header["Accept"], ",")
 
Ian

philip...@searchdiscovery.com

unread,
Jan 18, 2016, 11:12:34 AM1/18/16
to golang-nuts
The behavior is not the same.  If a request containing multiple Accept headers with different values is equivalent to a request with a single Accept header with comma separated values (and I believe they are), I should not see different results when I run request.Header.Get("Accept") against these equivalent requests.  I believe this is something that should be fixed.

C Banning

unread,
Jan 18, 2016, 12:59:42 PM1/18/16
to golang-nuts, philip...@searchdiscovery.com
Doesn't

   ss, ok := request.Header[http.CanonicalHeaderKey("Accept")]; if !ok {
        // header key doesn't exist
  }
  // do something with ss it's a []string value

work consistently for single or multi-valued keys? 
Reply all
Reply to author
Forward
0 new messages