Accept Headers for HTML Tags

Tags: HTML, REST, Accept Header

RESTful services are in fashion at the moment, but there is some disagreement as to what actually constitutes RESTfulness (if that is an actual word). A lot of times I hear that a service is RESTful because it uses HTTP or because it has a pretty URL. One thing I rarely hear is an emphasis on different representations of a given resource.

Consider the the two different URLs:

  • http://domain/resource.xml
  • http://domain/resource.json
  • http://domain/xml/resource
  • http://domain/json/resource

They are common ways of expressing different representations of a resource, which is supposedly the same. The human reader can may read them as the same, but they are different URLs by the definition of the HTTP standard. They should all really just be http://domain/resource.

One of my main annoyances when looking at supposedly RESTful services cannot return different representations. When the user sends a request it should be possible to specify in which form he wants the response. According to the HTTP standard, this is done, as you most likely know, by setting the Accept header. There may be limits to the capabilities of the service, but it should not be necessary to request different resources (by which I mean different URLs).

This is fine and well on the service end, but the consumer should also play by the rules and send a request with an Accept header that gives the service a chance to respond correctly. Arguably the browser is the primary REST consumer, so it should also be a requirement that it generates requests with proper Accept headers, not only for a page itself, but for the content that is being requested in the individual content elements, most notably the script and image elements.

I set up a resource that shows the location of the requesting IP address at IP Location. The basic HTML representation is:

<script src="/ip" type="text/javascript"></script>
<h2>IpLocation</h2>
<p>Location: 12,34 </p>
<div>
	<img alt=", " src="/ip" />
</div>

The idea is that when the browser requests the URL it should generate three requests, each for their own representation. The initial request is expected to request an HTML representation. The image tag on the page is expected to request an image representation and the script tag is expected to request a JavaScript representation. If all goes well the page should be showing text, an image and have a script element with a JSON object.

If you haven't already clicked the link, I can reveal right now, that Internet Explorer is the only one that sends the correct headers and displays the content in the browser as intended.

Looking at the headers from the different tested browsers we can see that Chrome starts with a proper header for the initial request, which means it gets a sensible HTML response. But for the image and the script elements, the Accept headers are simply */*. This basically means that Chrome is saying: "Give it to me any way you want". That is probably the safest way of getting a useless response, and it seems strange that Chrome doesn't even attempt to send something that is even remotely relevant.

Chrome Accept header:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept: */*
Accept: */*

Firefox is a bit better, sending correct Accept headers in two out three requests. Only for the script request does it send a */* blanket request.

Firefox 5 Accept header:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept: */*
Accept: image/png,image/*;q=0.8,*/*;q=0.5

As revealed above, Internet Explorer 9 does it right three out of three times.

IE 9 Accept header:
Accept: text/html, application/xhtml+xml, */*
Accept: application/javascript, */*;q=0.8
Accept: image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5

So if you do are going to view the location in a browser, I would suggest doing it in IE9.

Latest Tweets