tags:

views:

324

answers:

3

Hi guys,

Ok, here is the fact. StackOverflow is implemented REST-style. When you visit a specific questions/$id/ URL you get to see the question. The content is returned in HTML because it's what the browser understands.

I have to develop my own REST service. Fact is that I have to return multiple formats for the same information. For example, the default could be HTML, but I could return also an XML or a JSON.

Question is: what is the recommended style to achieve this ? Three choices (more from your helpful suggestions)

  1. option in the URL (e.g. http://example.com/questions/12345/?format=json )
  2. different interface (e.g.: for json data you have http://example.com/questions/1234/json/ or http://example.com/json/questions/12345/, for xml data you have http://example.com/questions/1234/xml/ etc... you get the point)
  3. http header Accept: application/json

Same is for PUT (POST) operations. If I want to submit data in different formats, I need to inform the receiver the format I am providing, so the same situation (and question) holds.

Thanks!

Edit: Additional proposal is the following

4) Specify a proper URL for each format e.g. http://example.com/questions/12345.json . This looks nice, but wouldn't this mean that, for consistency, we should also have http://example.com/questions/12345.html ? sounds so 1995... :)

PS: I hate markdown putting an arbitrary order to the list. If I want to start with 4, I should be able to do it.

+2  A: 

I would go for Option 1 (URL parameter) as it's the most consistent with the principles of REST, and the most pragmatic.

Option 2 smells bad - you're talking about different representations of the same resource, so you should use the same URI for them.

Option 3 smacks of being too hard to control - how would you hand-test it from within your browser, for instance?

(The same arguments apply for PUT / POST.)

RichieHindle
Thanks. do you think that it would be better to specify a simple string (format=json) or the mime-type (format=application/json) ?
Stefano Borini
I disagree with the assertion that option number 1 is the most RESTful. Can you elaborate on your reasoning? :)
Emil H
@Stefano: I would keep it simple: `format=json`
RichieHindle
@Emil: Having multiple URIs for the same resource feels wrong to me. (OK, arguably the `?format=json` is part of the URI, but you know what I mean.)
RichieHindle
That's actually a great argument, and I have to admit that my offering was misguided. I still feel that a header would be a better option than a get-parameter, though. It's true that it would be harder to hand test from a browser, but for those purposes it's probably fine to look at a single representation. It's quite possible to make sure that the actual serialization to different formats works fine using regular unit tests.
Emil H
It would be possible to compromise here, though. Add support for both the accept-header and a get-parameter. Client applications can specify representation using the header, and you can use the querystring when debugging from a browser.
Emil H
Option 3 is very easy to test with a browser. Get the Firefox plugin Poster. Any web developer should have this (and other) browser plugins. It allows you to set any HTTP Headers you want and make any type of a request (PUT, POST DELETE...) to a URL.
Gandalf
+2  A: 

It doesn't matter in the slightest between 1. and 2. A URI is opaque, so from the REST interface part of it, there is no difference.

From a caching perspective, 1. will prevent many caches from doing their work.

  1. is fine if you want to do conneg against multiple represetnaitons.

Usually though, people use conneg with Accept header, possibly with a redirect to the fully qualified URI using /customer/21.json

serialseb
+5  A: 

Option #3, setting the HTTP "Accept" header, is more in keeping with the HTTP specification and, among REST purists, is considered most correct. It also means that you keep the same URL (resource) no matter what the representation is.

You may, however, encounter user agents that aren't capable of setting an Accept header, so supporting a backup mechanism for specifying the response format is advisable. In that case, I suggest a URL query string parameter. Using a URL query string parameter means you keep the same core URL, no matter the content type returned. This makes it clearer that clients should only issue a PUT to that URL and not to the /foo/bar.json or /foo/bar.xml URLs.

Edit: Another thing to consider if you decide to go with the URL suffix (i.e. foo.json vs. foo?format=json) is that you may run into issues with caching proxies. If someone issues a PUT to /foo.json, a proxy won't interpret that as a request to invalidate /foo.xml. If, however, you use /foo?format=json, then it's all stored under the same resource (/foo) in the proxy.

Ryan Kennedy
AFAIK most caches will simply ignore any URI which includes a query string, rather than separate the URI into its base and store that.
Wahnfrieden