About Me

My photo
Ravi is an armchair futurist and an aspiring mad scientist. His mission is to create simplicity out of complexity and order out of chaos.

Friday, July 23, 2010

REST

REST (REpresentational State Transfer) is a simple architectural style or philosophy
  1. that needs you to identify or address entities in the system (called "resources")
  2. and that defines the actions or operations on those entities ("access methods").
The addressing mechanism is the URI - uniform resource identifier. e.g. http://www. google.com. The supported actions or operations are PUT, GET, POST and DELETE. In particular, PUT has creation semantics, GET has fetch semantics, POST has update semantics and DELETE has remove semantics.

Universal applicability
Because of its simplicity, REST has almost universal applicability. As an example, consider a book:
  • It can be considered as a resource and referred to by its book number (ISBN, e.g. 9871234567890). So its URI can be isbn://9871234567890.
  • You can write a new book by PUTting a new resource accessible at this URI.
  • You can fetch the book by GETing it from the URI.
  • You can modify the book by POSTing to the URI.
  • You can delete the book by DELETEing the URI.

HTTP is the best known usage of REST.

Details
One of the biggest values offered by REST is the standardization of its access methods. If you came up with different access methods (i.e. verbs) to access different resources, that proliferation would be so hard to track as to be of little value. Imagine that for dealing with books, your methods are "createBook", "getBook", "updateBook", "deleteBook" and for dealing with printers, they are "createPrinter", "getPrinter", "submitPrintJob", "deletePrinter". You need to know the resource type (in this case, book v/s printer) to know the operations that it supports. This customization leads to chaos even with a small number of resource types. With uniformity of access methods comes confidence that (a) you know beforehand what access methods are supported and (b) using an access method will result in (more or less) what you think it should result in.

REST standardizes the addressing mechanism (URI) and the access methods (GET/PUT/etc.). It does not standardize the message format, i.e. the data/information flowing over the REST mechanism. E.g. you can use binary, XML, JSON or your favorite message format and still conform with REST principles.

Since PUT has creation semantics, it must be idempotent, i.e. multiple executions of PUT with the same message must be no different than a single execution. Additionally, GET must not change the state of the system. This implies that GET must be idempotent too, i.e. multiple GETs (without any POSTs in between!) should return the same representation. POSTs are expected to change the state of the entity and are not expected to be idempotent. Similarly, DELETEs are not expected to be idempotent either. One of the implications of state change and idempotence is the opportunity to cache resource representations between the resource and its clients, which can improve performance.

How to apply REST to your system
One way to RESTify your system is to:
  1. Identify the top-level, first-class nouns in the system. These become your resources.
  2. Choose meaningful identifiers in your URIs for these resources. Usually these identifiers should be long-lived, i.e. their commonly-accepted meaning should rarely change with time. They should feel relevant and meaningful to the largest subset of the client population. E.g. instead of an obscure, numeric id (e.g. user id) for a resource, a more descriptive identifier (e.g. user name) may be a better choice.
  3. Verbs/operations in the system are restricted to one of create (PUT), get (GET), modify (POST) or delete (DELETE). Their semantics should be defined as they apply to the resources. It is acceptable for POST (for example) to mean differently to different resources. E.g. POST for a book resource may mean updating the book's contents, while POST for a printer may mean "submit a print job".
  4. Make sure that GETs and PUTs are idempotent. Specifically, make sure that GETs don't change the state of the system.
That's it! Your system is now REST-compliant (or RESTful). Of course, this is a simplication and each of the steps above take non-trivial time. But on a high-level, that's all that's usually involved.

Common mistakes
  1. Sometimes, system designers make GET change the state of the system. This is the most widespread violation in my experience, e.g. when GETs are used to submit data to resources to change their state. E.g. HTTP URL like "AddToCart?item=candy" - this is a violation of REST principles. (In this specific case, POST is the right access method, since your resource is really the "cart" and you are updating it.)
  2. Another common violation is PUTing to a URI that isn't being created. E.g. when creating a new print job to the printer, you usually don't know the resource to create. But you do know the printer URI. In this case, POSTing is the right option. 

Comparing REST with SOAP RPC
This uniformity/standardization of access methods is the fundamental difference between REST and SOAP RPC. While REST allows only PUT/GET/POST/DELETE, SOAP RPC encourages ad-hoc or custom access methods (GetOrders, AddToCart, SubmitPrintJob, etc). This implies that to use SOAP RPC, you need to know the access methods a priori. This can be a big disadvantage if you are targeting universal access.

Another fundamental difference is that SOAP is a protocol, REST is not. REST is more of a guideline or a principle. If someone says, "I am using the REST protocol", now you know how much they really know about REST!

One comment I frequently hear is "we can either use REST or XML, not both". This implies that XML over REST is impossible. That's not the case. Recall that REST does not define a message format. Here's how you use XML using REST principles. You can define resources in your system, define URIs for them, restrict access methods to PUT/GET/POST/DELETE and then allow these access methods to use XML. Viola! You are now using XML with REST.

The flip side
When it comes to generality of access pattern, nothing comes close to REST/HTTP. Using a single browser, you can access almost any resource (text (txt, html, etc.), images (gif, jpg, png, etc.), sounds (mp3, ram), video (mp3, mp4), etc.) on the web. This is a clear advantage of REST. However, this doesn't mean that you have to use REST all the time. REST thrives when clients know and use generic access patterns (e.g. GET/PUT). If that is not the case, then REST is not needed. E.g. when a resource is being used by a small number of clients, each of them can have knowledge of the specific operations supported by the resource. In this case, it can be argued that REST doesn't add much value.

In Closing
REST, as an architectural principle, uniformalizes resource identification and access. This uniformity is of enormous value in general and has led to some great things, e.g. HTTP over the internet. However, before you jump onto the bandwagon, it never hurts to know your reasons.

References:
  1. http://www.prescod.net/rest/
  2. http://en.wikipedia.org/wiki/REST

No comments:

Post a Comment