REST Versus The Real World

Over the last few months I have been working on and off creating a node module designed to easily expose a RESTful interface to MongoDB powered data layer. I will talk more about this module soon (it will be open source) but let me say that at some point along the way I became obsessed with achieving the perfect RESTful implementation. At points my obsession may have bordered on martyrdom, but alas (or thankfully) I have now come to realise that the perfect RESTful API is a utopia I will never enjoy. You may well be a soldier in the army of seasoned API developers who have experienced my plight before, but if you are not, let me explain that there are many considerations each with their own ‘standards’, and often conflicting best practise interpretations, to consider when constructing a REST API. Something as simple as choosing a name, or selecting a plural word over a singular, can require serious consideration when it comes to the REST minefield. During the last few months while I have been battling with these considerations I have had many conversations and debates with peers while trying to flog out which choices are the best way to go, and have included examples of considerations with our advantages and disadvantages below *. * to understand the inflection related advantages you need to know that the module uses dynamic routing based on the available database definitions and are not always defined until runtime

1. The Inflection Debate.

The inflection debate relates to whether resource names within URLs should be named using only plural nouns, a combination of singular or plural nouns depending on context, or either in any context. Here are examples of each: a) GET http://api.host.com/countries GET http://api.host.com/countries/123 POST http://api.host.com/countries PUT http://api.host.com/countries/123 b) GET http://api.host.com/countries GET http://api.host.com/country/123 POST http://api.host.com/countries PUT http://api.host.com/country/123 c) Any combination of the above. Advantages of A: Easier to implement than B, you only have to check for plural inflection. Client side code may be easier. Disadvantages: I feel like a singular object, so use a singular noun. Feels slightly ‘hacky’ in a way. Advantages of B: To me these feel like more natural English, when dealing with a singular resource you are using a singular name. Also makes it easier to see which type of resource you are working on – creates more separation between resources and resource sets. Developers need to read the documentation properly. Disadvantages of B: Requires slightly more complicated inflection checks. Developers need to read the documentation properly. Advantages of C: No inflection checking necessary, easiest to implement and easiest to document. Disadvantages of C: Clients can be inconsistent with their API calls. Clients may break if you decide to change this later.

2. The Payload Item Name Debate.

This debate relates to what items in the JSON response payload should be called when a successful get operation is performed. The options we considered were, “item”, “resource”, or resource name (singularised). a) { “item” : { “id” : 123, “title” : “My Item” } } b) { “resource” : { “id” : 123, “title” : “My Item” } } c) { “message” : { “id” : 123, “title” : “My Item” } } In this case, there is little difference between A and B other than personal preference. However in the case of option C, which during my research seems to be the most common way to name the response, there are subtle differences. Mainly the differences affect client-side implementation. One disadvantage of using option C over A is simply an increased requirement to modify code on the client side when implementing a new resource model. In favour of option C however, is the fact that amnesic developers like myself will never forget which type of resource they are manipulating.

3. The URL Versus Accept Header Version Debate

This debate relates to versioning APIs, there are two popular options which APIs commonly utilise including URL and Accept Header. URL looks like this: http://api.host.com/v1/countries And Accept headers looks like this: http://api.host.com/countries Accept: application/vnd.company.myapp.customer-v1+json I’m not going to go into the advantages and disadvantages to these, I’m sure you have got the idea by now… There are a lot of different options with different pros and cons to consider. While these considerations may seem trivial it got to the point where I was making hardly any progress with development due to constantly breaking off to research and have debates over every choice that came up. Just as I started wondering whether it was even worth it, I stumbled across this podcast: A Creating API Show – NodeUp Daniel Shaw, James Halliday, Mark Cavage (author Restify), Andrew Sliwinski discussing creating APIs. In this podcast at around 24:40, they joke about how they won’t even implicitly state that their APIs are JSON any more, let alone RESTful. They go on to talk about how statements like “This is a REST API” are Trollbait for pedantry about REST. They also mention how much time can be lost in the trivial decision making of trying to achieve a perfect RESTful API. This reflected the feelings I was starting to develop, and made me revolve that my attitude would have to change for progress to be had. One thing that they do mention later on in the Podcast is that you should stick to the HTTP specification religiously – 100% agree. I recommend listening to the full Podcast, but essentially the things I took away from it are: • It’s OK not to stress-out about following the perfect REST ‘best-practises’ • Ensure you follow the HTTP specification • Make your API interfaces as simple as possible Moving forward I will simply use the practises I prefer to use most for designing restful web apps, based on my own research and opinion, add follow the above rules and stop worrying so much about trying to create the perfectly RESTful API. I’ve concluded that the perfect REST API is not compatible with the real world. What do you think about RESTful web services implementation and how do you deal with these implementation considerations?