When developing an API, one of the first critical decisions every developer must face is that of Content Type. In this day and age most APIs return one or both of JSON or XML.
Some APIs get away with one, and that’s fine, but to improve the UX of your API, you should allow the requestor to determine what data type is best for them. If you’ve read the post on API Content Negotiation, you’ll know the best way to approach content negotiation is to follow the standards.
However, as is the case with many standards, it can be difficult to read the Header Definitions standard. It’s easy to understand the difference between “Accept: application/json;” and “Accept: application/xml;” – But are you sure your service will respond correctly if to a request specifying “Accept: application/xml;q=0.5, application/json”? It’s a perfectly valid request, and should be handled properly.
Parsing the Accept Header
While the spec can be quite daunting to read through, fortunately the actual parsing is fairly straightforward and intuitive. The key to understanding the how the Accept header specifies which content-type is actually desired boils down to three points, in order of how they should be looked at while parsing:
- Quality (q-param)
Specificity indicates that if a server can supply either of two given formats in an Accept header, it will supply the more specific one. This will take into account parameters (other than the special q-param) as well – rarely used, but valid; for example “text/html;level=1” may mean something to a server. If a server were asked to respond to “text/*, text/html, text/html;level=1”, it would respond with level 1 HTML first if possible, then any other HTML, then any textual information.
Quality, or the q-param, is a special parameter that can indicate a preferential order determined by a quality scaling parameter. In theory, the quality parameter could be used with some sort of quality determination of the available content types. If the application could only serve up a 50% quality audio/mp4 file but a 100% quality ogg file, and the Accept header specified that it wanted audio/mp4 at a 1.0 scale but ogg at 0.9 scale (“Accept: audio/mp4, audio/ogg;q=0.9”), the ogg file would be served as its scaled quality (90%) beats the inferior mp4 scaled quality (still 50%). In practice, however, the q-param is more often simply used to override the order as few services actually measure the quality of various content types.
Order, finally, is the most common scheme for determining what content-type the requestor desires. The given two accept types with the same specificity and scaled quality factor, the server should send the first type as the response.
Utilizing the Accept Header
Why should you use the Accept header? So many APIs can simply get by with a string comparison against “application/json” or “application/xml”, why is it important?
In a trivial example, an API is simply an agreement between the provider and users that when a certain type of request comes in, the API will respond a certain way. However, some otherwise valid requests – for example, “complicated” Accept headers – may be rejected, or worse, respond in a poorly defined manner if you stray outside the agreement. Determining and defining every possible accept header can become burdensome if you’re serving up multiple media types.
When you agree to follow the standards, a lot of the heavy lifting is done for you. One of the keys to a beautiful user experience is to behave in an intuitive manner rather than assume the user knows your rules. So next time you’re working on an API, remember the Accept header!