RESTful Content Negotiation

/ April 6, 2010 in 

Client: “I want JSON.”

Server: “Silly client, you think it’s going to be that easy? If you ever want to see JSON alive again, you’re going to have to give me one million dollars.”

Client: “How do I even know that you have JSON?”

Server: “Why don’t you ask him yourself?” [Puts JSON on the line]

JSON: { “voice”:”HELP ME!!!”, “emoticon”: “:-o” }

Client: “I’ll get the money…”

We’ve all been a part of these sorts of heated content negotiations in the past, and want to avoid them in the future. That’s why it’s important for HTTP clients and servers to communicate in a clear and consistent manner which representation will be returned for a request.

As the client, you are free to specify the representation that you prefer via the HTTP Accept header. The server will read in the header, and make its best judgment on which representation to return.

This negotiation could look something like:

Client Request

GET /dictonary?synonym=happy HTTP/1.1
Accept: application/json

Server Response

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 512
{"status": "OK", "synonyms": [{"synonym": "chipper"}, {"synonym": "glad"},
{"synonym": "pleased"}, {"synonym": "tickled"}]}

However, if the requested representation is not available, the server is free to either send back the representation it does have, or to return an HTTP Response Code 406 (not acceptable). This exchange between the client and server is the actual negotiation.

Representation Preference

It is important to note that the client is not limited to listing one representation in the Accept header. In fact, the header can include a comma-delimited list of acceptable content types, each optionally with a quality value for preference ranking. The quality values range from 0-1, with 1 being the most preferred representation. Take the following example:

Accept: application/json;q=1, text/html;q=0.5; application/xml;q=0.1

This lets the server know that the top preference is for “application/json”, followed by “text/html”, and finally “application/xml”.

Here are some other things to keep in mind when specifying representation preferences:

  • A representation is composed of the type and the subtype, in the following format <<type>>/<<subtype>> (ex. “text”/”html”)
  • A “*” represents a wildcard (technically referred to as a media-range). “*/*” means any representation available. “application/*” means any subtype of application.
  • A (blank) Accept header means that any representation is acceptable

There are several other, less known rules with regard to representation preference; it is recommended that you see the HTTP/1.1 Specification for more details.

Alternative Negotiation

A common alternative mechanism for requesting a specific representation is to append an extension to the resource being requested, and leave the Accept header blank. Using this approach the original request from above would be modified to read like the following:

GET /dictonary.json?synonym=happy HTTP/1.1

Note: Although common, this alternative for content negotiation is not an HTTP 1.1 compliant mechanism for requesting representations.

Summary

Resources can have several different representations. It is up to the client and server to negotiate (hopefully without kidnapping and ransom requests) which representation will be returned. The client does this by listing out which representation it prefers in the HTTP Accept header. If available, the server will return the requested representation.

Previous

REST: Resources and Representations

Next

HATEOAS

Close Form

Enjoy our Blog?

Then stay up-to-date with our latest posts delivered right to your inbox.

  • This field is for validation purposes and should be left unchanged.

Or catch us on social media

Stay in Touch

Whether we’re honing our craft, hanging out with our team, or volunteering in the community, we invite you to keep tabs on us.

  • This field is for validation purposes and should be left unchanged.