Tom Insam

Opinions on REST

I wrote a thing about what is and isn't REST. That was (what I believe are) the facts. This bit is opinion.

Things that actually matter:

  • You've shipped something.
  • Your API has client libraries, even if they're trivial wrappers (because people will complain otherwise, or write bad ones).

REST is a nice dream. But I'm not personally a fan. RPC is how programmers' minds work, is the problem. Call method, receive bacon.

Here are some top-of-the head problems with a pure REST API:

  • Result pagination - suppose /books/ returns 1 million books? How do I know how many there are? Maybe it returns a list of pages? Suppose there a million pages? Does it merely return the first page and a link to the next one? How do I get page 100? Stack Overflow mentions the Range header, but I can't just magically use this as a client - the documentation will have to tell me what values are valid for this header. (Does the Range header even go in the OAuth signature? It seems not. Is this a security problem?)

  • How do I even find the links in the first place? Look for any string in the returned data structure that matches ^http://? Presumably the response format needs to be documented, and responses are going to differ based on the sort of object I'm requesting, so in practice, you're going to have documentation that says 'responses for URLs under /books/ look like this', and your URL structure is exposed again.

  • Am I allowed to make verbs up? Suppose I want to be able to flag a particular resource as offensive. Do I post to /books/4/offensive (how do I discover this URL), or POST offensive=1 to /books/4 (but I'm not changing the state of a book, so that doesn't seem right either)?

These aren't big problems. They have obvious solutions, even. But the solutions aren't covered by just saying 'It's REST' - you need to document them.

As a new developer, the main thing a purely REST API is going to differently is that, when I want to do pagination, the docs won't say 'add a page parameter', they'll start talking about Range headers. When I want to get JSON back instead of XML, I'll have to look at Accept headers. When performing operations on objects, they need to work out which verb is appropriate here.They will need to store complete URLs to your objects in their database rather than just IDs. (In practice, they'll just reverse-engineer your ID-to-URL mapping and store the IDs, then complain when you change something and their code breaks.)

Or maybe the developer will be using a high-level client that hides all of this, in which case there is no difference, except that your client libraries have to be a lot more complicated. But you've also hidden most of the benefits.

In practice, you will still end up documenting all of your different resource types, what URLs you can find them under, how to parse their representations, and how to find other objects based on those representations. You'll just have to document them using lots of highly-specific HTTP language, which means your documentation is going to be much harder to use for all the people using clients that hide all this stuff.

The best flickr clients (to my mind) are the ones with a call_flickr( method, params ) function, that takes one of the Flickr API methods, adds the parameters to it, does the authentication signing dance, and returns you the response, parsed into some in-memory data structure. To do this requires some knowledge of the Flickr API, sure, and I can't just point this client to some other web service's endpoint and get data out. But REST doesn't solve this problem either, and I believe it makes the simple things harder.