views:

141

answers:

3

Several of our users have asked us to include data relative to their account in the HTTP headers of requests we send them, or even responses they get from our API. What is the general convention to add custom HTTP headers, in terms of naming, format... etc.

Also, feel free to post any smart usage of these that you stumbled upon on the web; We're trying to implement this using what's best out there as a target :)

+8  A: 

The normal approach is to start their name with X-. E.g. X-Forwarded-For, X-Requested-With. This is also mentioned in section 5 of RFC 2047.

BalusC
Just an X? What about case? Looks like it should be camelized? Also, what about the format on the value itself? Text, JSON, anything?
Julien Genestoux
It's case-insensitive. As to the content, as long as it is ASCII, you can in fact just put anything in. You can consider to URL-encode or Base64-encode non-ASCII characters resp. bytes.
BalusC
IIRC, HTTP headers are ISO-8859-1 rather than ASCII, and there's also a highly arcane escape mechanism to express characters in other encodings. Probably sensible to stick to ASCII for interoperability, though.
Tom Anderson
Well, the 2 examples you posted had a very specific choice for the case I believe. Also it seems that namespacing the params with X-Company-Xyz is a best practice.
Julien Genestoux
@Tom: afaik, the headers should be US-ASCII only, the body indeed defaults to ISO-8859-1, unless otherwise specified in `Content-Type` header. @Julien: as long as it starts with `X-`, you will be guaranteed that it isn't ever going to be standardized in HTTP specs.
BalusC
@BalusC : oki, cool then. I'll still add our app's name so that it doen't conflict with anyone else's either.
Julien Genestoux
Consensus of the uninformed? There's nothing special to "X-" in HTTP headers.
Julian Reschke
@Julien Genestoux: Content-Type describes the message body, not headers.
Julian Reschke
@BalusC: Not so, my dear fellow! This comment box is too narrow to contain my proof, so i will make another post ...
Tom Anderson
+1  A: 

The header field name registry is defined in RFC3864, and there's nothing special with "X-".

As far as I can tell, there are no guidelines for private headers; in doubt, avoid them. Or have a look at the HTTP Extension Framework (RFC 2774).

It would be interesting to understand more of the use case; why can't the information be added to the message body?

Julian Reschke
Thanks for the links, I realize that custom headers is not an ideal solution, I just thought that the 'x-' prefix had become an accepted community convention.
Darrel Miller
I think they *are* an accepted community convention, even if it's not (yet) reflected in the RFC.
Kylar
Special support for "X-" was *removed* on purpose; because it doesn't work in practice. Once a name is in use on the public internet, you won't rename it anyway.
Julian Reschke
+1  A: 

The format for HTTP headers is defined in the HTTP specification. I'm going to talk about HTTP 1.1, for which the specification is RFC 2616. In section 4.2, 'Message Headers', the general structure of a header is defined:

   message-header = field-name ":" [ field-value ]
   field-name     = token
   field-value    = *( field-content | LWS )
   field-content  = <the OCTETs making up the field-value
                    and consisting of either *TEXT or combinations
                    of token, separators, and quoted-string>

This definition rests on two main pillars, token and TEXT. Both are defined in section 2.2, 'Basic Rules'. Token is:

   token          = 1*<any CHAR except CTLs or separators>

In turn resting on CHAR, CTL and separators:

   CHAR           = <any US-ASCII character (octets 0 - 127)>

   CTL            = <any US-ASCII control character
                    (octets 0 - 31) and DEL (127)>

   separators     = "(" | ")" | "<" | ">" | "@"
                  | "," | ";" | ":" | "\" | <">
                  | "/" | "[" | "]" | "?" | "="
                  | "{" | "}" | SP | HT

TEXT is:

   TEXT           = <any OCTET except CTLs,
                    but including LWS>

Where LWS is linear white space, whose definition i won't reproduce, and OCTET is:

   OCTET          = <any 8-bit sequence of data>

There is a note accompanying the definition:

The TEXT rule is only used for descriptive field contents and values
that are not intended to be interpreted by the message parser. Words
of *TEXT MAY contain characters from character sets other than ISO-
8859-1 [22] only when encoded according to the rules of RFC 2047
[14].

So, two conclusions. Firstly, it's clear that the header name must be composed from a subset of ASCII characters - alphanumerics, some punctuation, not a lot else. Secondly, there is nothing in the definition of a header value that restricts it to ASCII or excludes 8-bit characters: it's explicitly composed of octets, with only control characters barred (note that CR and LF are considered controls). Furthermore, the comment on the TEXT production implies that the octets are to be interpreted as being in ISO-8859-1, and that there is an encoding mechanism (which is horrible, incidentally) for representing characters outside that encoding.

So, to respond to @BalusC in particular, it's quite clear that according to the specification, header values are in ISO-8859-1. I've sent high-8859-1 characters (specifically, some accented vowels as used in French) in a header out of Tomcat, and had them interpreted correctly by Firefox, so to some extent, this works in practice as well as in theory (although this was a Location header, which contains a URL, and these characters are not legal in URLs, so this was actually illegal, but under a different rule!).

That said, i wouldn't rely on ISO-8859-1 working across all servers, proxies, and clients, so i would stick to ASCII as a matter of defensive programming.

Tom Anderson