i don't like fahrenheit. it's nothing personal, but they are hard to get used to, as much as (i guess) celsius are hard to adjust to for fahrenheit-centric people. this means that in many cases, it would be great to see web pages in metric units, and well-done internationalized sites often have that option. but unlike language preferences, which can be communicated via HTTP, there is no such mechanism for measurement systems (and the many other dimensions along which a service might want to provide choices).
so what would it take to extend HTTP in a way that content negotiation is more generic and not restricted to the currently hardcoded set of negotiable dimensions? this is just a first thought experiment, and i am wondering how useful this might be.
instead of hardcoding the negotiation axis in the header field, it should be dynamic, but there also should be some set of values for which a shared meaning (such as the axes hardcoded into HTTP now) has been established. an easy way to achieve this is to say that a negotiation axis is identified by token or by URI, where tokens have to be registered (in the same way as link relations can be registered in the IANA link relation registry), while URIs can be freely used and require no registration (like extension link relation types).
let's assume there's a registered "temperature" negotiation axis. a client could request to get responses in metric units by using an HTTP header field similar to Accept-Language, but since the axis now is configurable, let's assume we use a generic Accept-Axis header field:
Accept-Axis: "temperature" celsius;q=1, fahrenheit;q=0.7, kelvin;q=0.5
the syntax is similar to Accept-Language's language negotiation (or Accept-Encoding or Accept-Charset), only that it also includes an axis identifier. in the same way as Accept-Language defines the rules for how to match requested and available languages, the "temperature" axis has to define the same matching rules. in case of temperature system identifiers, all that's required is probably comparison, but other axes may specify more complex rules, such as the matching of language tags.
in the response, similar to Content-Language but using a generic header field, the server specifies which value has been chosen for a particular axis:
Content-Axis: "temperature" celsius
both the Accept-Axis and the Content-Axis header field can be repeated, so that it is possible to specify multiple axes in both requests and responses. however, this might produce an unwanted overhead, in particular if multiples axes are support. it thus would be possible to advertise the available axes via special headers. for example, a request could specifically ask to get information about a set of axes:
Accept-Axes: "temperature" "weight" "length"
this way, a server could make sure to only serve information about these axes in the response; any other available axes would not be exposed via Content-Axis headers. if a client wants to see all supported axes, it can send the following request header:
since such a request header field can be sent in an OPTIONS request, a server should have a way to simply list the available axes, which could be done as follows:
Content-Axes: "temperature" "weight"
when getting this information, a client can adjust the requested axes according to the supported ones. when combining link hints with this mechanism, overhead could be kept pretty low. when a client follows a link, that link could already specify the supported axes in an axes hint similar to the formats hint. however, when following the link, the client might also include an Accept-Axes header, allowing it to inquire about the runtime capabilities of the server (as opposed to the capabilities advertised in the link hint).
in the services that we provide, we actually have a fair number of "negotiation axes". some of them are not so much across the traditional lines of language or temperature, but for example control whether resources are sent in a more minimalistic way (excluding certain navigation options in the hypermedia format), or as fully interlinked resources. while this is not something that perfectly fits the traditional content negotiation bill, it might still be a good fit for a generalized HTTP content negotiation feature:
this way, we might (in our specific, non-standardized and non-registered way) expose the ability of a resource to be represented in two variants, with the axis supporting two values for sparsely or fully interlinked resources. clients can then request a specific variant by specifying the desired linkage:
Accept-Axis: "http://identifiers.emc.com/axis/linkage" sparse;q=1, full;q=0.5
currently, we are using query parameters for this kind of "negotiation", but it seems that pushing it into HTTP's uniform interface might make interactions a little bit simpler, but of course it would have the usual side-effect of content negotiation, meaning that there would be no separate URIs for the two variants.
i still need to think about how all of this affects caching (probably in a way which would make these interactions not very cache-friendly), and how it relates to Transparent Content Negotiation (TCN) as specified in RFC 2295. TCN probably could be extended to also cover generalized content negotiation, but currently TCN's dimensions are limited to the ones that are built into HTTP.