Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm working through designing a RESTful API. We know we want to return JSON and XML for any given resource. I had been thinking we would do something like this:

GET /api/something?param1=value1
Accept:  application/xml (or application/json)

However, someone tossed out using extensions for this, like so:

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

What are the tradeoffs with these approaches? Is it best to rely on the accept header when an extension isn't specified, but honor extensions when specified? Is there a drawback to that approach?

share|improve this question
    
What webserver you are using? and how does it parse URLs? –  Dipan Mehta Mar 14 '12 at 4:58
1  
I have no idea about the technical (server) side of things. That being said, I prefer your approach, because it uses the http standard, which makes it easier to understand (for example when somebody else is supposed to do some maintenance on it a few years down the road). You could rely on the extension when the accept is not specified, or has an unexpected value, but I would always go with the standard way first. –  Treb Mar 14 '12 at 8:21
    
@Dipan I'm hacking this out with the MVC4 Web API (still in beta). It uses ASP.NET's routing abstractions, which are pretty nice. –  Brandon Linton Mar 14 '12 at 13:42
    
@Treb Yeah I'm much more a fan of using the accept header value. I'm wondering if there's any drawback to supporting both. –  Brandon Linton Mar 14 '12 at 13:43
add comment

4 Answers

up vote 13 down vote accepted

This, "However, philosophically - the first approach is the only approach.", and this "The proper official RESTful approach is to use Accept: header." are widely perceived to be the case, but are also absolutely incorrect.

Here's a brief snippet from Roy Fielding (who defined REST)...

"section 6.2.1 does not say that content negotiation should be used all the time." cite

That particular conversation is in the context of the 'Accept-Language:' header, but the same applies equally to the 'Accept:' header, as made clear later in his response...

"I have no idea why people can't see the second and third link on the top page

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

that point to the two PDF editions."

What he means there is that there's no issue in using different endpoints for different representations of the same source data. (In this case one .html endpoint and two different .pdf endpoints.)

Also in a similar discussion, this time regarding the virtues of using query parameters vs. using file extensions for different media types...

"That's why I always prefer extensions. Neither choice has anything to do with REST." cite

Again, that's slightly different to Accept vs. filename extensions, but Fielding's stance is still clear.

Answer - it really doesn't much matter. The trade-offs between the two aren't very significant and both are acceptable styles.

share|improve this answer
    
+1, both are reasonably valid approaches. –  Wyatt Barnett Oct 19 '12 at 11:40
1  
Great balanced answer. I think I would add sometimes it is 'obvious' from the URI that a certain content is intended. e.g. .html extension or .pdf extension in the URI. And in this case there's really no need to support content negotiation, and having content implicit in the URI makes it easier for humans to share the URI and use it to link to things in a way they can immediately consume. In other cases such as you want to avoid extensions in your URIs, and/or you want to expose a web API that supports multiple content types json/XML equally, an accept header can fit better. –  Tim Lovell-Smith Dec 17 '12 at 19:30
add comment

The proper official RESTful approach is to use Accept: header.

However, you have to be careful not to break cacheability, which is one of REST's requirements. You need to have Vary: Accept header and cache which understands it. In ideal world you'd have it, but in real life your millage may vary. So the second solution isn't as clean, but it might be more practical.

Also, note that some very old browsers used to ignore headers, relying on the extension instead.

share|improve this answer
add comment

Technically it doesn't really matter - your web server will be able to pass process it appropriately as it looks like. (I am assuming this but doesn't look like a showstopper).

However, philosophically - the first approach is the only approach. In REST, the URL actually only points to a URI - which is only a resource. Think for a moment this resource same as object in object oriented programming. You talk to this resource through only 4 methods (aka GET/POST/PUT/DELETE -or if anything that transport allows) but that method doesn't become description of object. Same way, the aspects the return value is not the URI. The object is still something and not something.xml or something.json

Suppose if you don't want to use Accept header, but if you still want to be truly REST philosophically, i wont mind something like:

GET /api/something?parm1=value1&return_type=xml

as opposed to

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

But as i said, this difference is only philosophical.

share|improve this answer
    
+1 Dipan, you are right except for one thing: /api/something?return_type=xml is still not restful. The reason it is not RESTful is that URLs are opaque. IOW, from a protocol point of view, there is no difference between /api/something/xml and /api/something?xml. See w3.org/DesignIssues/Axioms.html. –  mehaase Jun 22 '12 at 21:41
add comment

@vartec: I think you are wrong

The proper official RESTful principle says nothing should be hidden in HTTP headers as it is the URI which is exposed or referenced, any detail about the request/response should be provided as part of URI

Hence i strongly recommend to avoid using header for details which about the request & response, and stick to

 GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

I am not able to find the references quickly, but i will post back with them (actually you could refer the O'reilly publication book "RESTful web services" (http://shop.oreilly.com/product/9780596529260.do) which confirms the same

share|improve this answer
8  
-1 Completely wrong. For one thing, the URL is sent in the HTTP headers. Furthermore, each distinct URL should represent a distinct resource. XML and JSON encodings of the same content are clearly not 2 different resources; they are 2 different representations of the same resource. –  mehaase Jun 22 '12 at 21:53
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.