XHTML is a tempting hypermedia format to use in a web service. A lot of the time, the sort of data that you serve using an API is very similar (if not the same) to what your website displays on its own. XHTML already has all the functionality built in for describing forms, where to post them back to once filled in, how to link to images, documents or any other form of data across the whole web of information.
Despite all this good stuff that you get for free, xhtml, or rather the xhtml media type (application/xhtml+xml) has its problems. And one of those problems is webkit.
Mobile devices are incredibly important in modern web development, so designing for the capabilities of those devices is just part of a standard workflow. The problem however, is that webkit on these devices prefer application/xml and application/xhtml over our friend, text/html. Take a look at the following Accept header sent by two desktop browsers (Firefox and Chrome):
Accept: text/html,application/xhtml+xml,application/xml;q=0.9, */*;q=0.8
Contrast this with what is sent from the iPhone (iOS 4.3.5):
Accept: application/xml,application/xhtml+xml,text/html;q=0.9, text/plain;q=0.8,image/png,*/*;q=0.5
And further, and Android phone (2.3.5):
Accept: text/xml, text/html, application/xhtml+xml, image/png, text/plain, */*;q=0.8
And suddenly we have a problem. If we use application/xhtml+xml then we have to account for iOS and Android devices preferring it over text/html.
There’s two things we can do to counter this. The first is to put a filter in front of your application to detect the user agents for browsers that are known to prefer the xml/xhtml representation that we want to reserve for our API clients. This is an application specific solution – you have to know that the browsers that you are filtering and then rewrite the Accept header so that text/html is served up by your application. You also have to accept that requests from those browsers will never be issuing requests against your web service as those requests will be rewritten to text/html.
The second solution is to use a vendor specific media type, and serve xhtml up on that. This means that you lose a small part of the self describing nature of using application/xhtml+xml – but means that you can be absolutely certain that no existing browser will prefer your API content over what it should be seeing. Vendor media types take the format of application/vnd.
Opinions on which of these two options are preferred (or if you have heard of other solutions or have any suggestions on other ways of dealing with this) would be most welcome.