Thursday, June 14, 2012

REST (3): why NOT easy: the details


Continuation of the previous post motivated by RESTful WebServices book.

In the previous post I have tried to identify the elements of REST and pointed out general problems around software development of RESTful web services.  I am considering REST based on the HTTP protocol only. 
REST is important concept and can yield many benefits to applications which decide to be strictly RESTful.

Here is a more low level detailed list of REST things which are not very easy to do.  (It is my private what I can screw up (or I did screw up) and where I should be careful list):

URLS
  • Constructing URL is NOT client job:  I believe we will see very few applications where this is met and it is obviously hard to achieve.  It requires excellent 'connectedness'. Designs where client needs to know how to construct URLs are not RESTful.
  • ? Restrictions:  Except for few spelled out exceptional cases using ? is not fashionable any more.  Unfortunatelly ?-marks are so easy to use:  just throw some parameters in and you done, you never have to rethink you URLs, you can simply add stuff to them to piggyback new functionality.  If you do that it is not RESTful.
  • No Database IDs:  Rails with ActiveRecord and Grails with GORM make using IDs easy.  These are not very useful especially when the service is not well connected. Imagine a fantasy Active Directory exposing REST interface, you want to get a phone number for jsmith.  Would you prefer to issue a GET to: .../users/jsmith  or  .../users/2001234?   Frankly, the second URL format is useless, yet you will find it in most Rails or Grails projects which claim RESTfulness and in fact this is what you get if you use Rails REST scaffold.
  • Lack of support for templates:  (example: /users/{userId}/posts/{topic}).  Few tools support templates.  GRAILS has UrlMapping file, but there are limitation to it as well.  I believe Rails, as I understand it, is more limited than Grails.
  • No Verbs please:  This may require extra effort and even rethinking of what are your resources.  URLs represent resources, so URLs containing verbs (.../myserver/mydatabase/runDefragmenter) are not RESTful.  How about POSTing to: .../myserver/mydatabase/defragjobs instead?  API-like thinking is very much ingrained in us.   API and REST should not be used in the same sentence (unless you think of the uniform interface).
Uniform Interface
HTTP protocol is the base for achieving the uniformity.  This goes beyond the 4 (or 6, or 8) HTTP verbs and requires understanding of the HTTP protocol itself with advanced use of headers, status codes, etc.  Defining HTTP protocol and explaining how it applies to REST is not what I want to do here.  I just want to point out that RESTful is not RESTful without it.  Here are some examples.
  • Status Codes:  Example 1: consider a PUT to a URL representing a resource with unique constraint on its name.  The PUT tries to rename the resource but a resource with the new name already exists.  I bet many apps will simply return status 500.  Correct code should be: 409 (Conflict).   
    Example 2:  As above, consider a PUT request to rename a resource and assume that resource name is part of the URL.  I bet may web services will simply return 200 and a new representation leaving to the client to 'construct' the new URL.  This is not optimal use of HTTP protocol and is not RESTful.
  • Other Header Stuff:  There is a bit to learn there and this will probably be overlooked by many developers writing RESTful apps.  This could create lack of consistency. 
  • Uniform Interface vs Serving Web Pages to the users  Typical 'MVC' web frameworks have you focus on flow of web pages.  Programming REST Uniform Interface is different.  Making both pieces of logic coexist is harder than it looks.  I will explain more in the next post.
Formatting resource representations
Standard Interface helps but its benefits are less inspiring if REST client coded by someone else has no way of understanding the content.
Coming up with a standard vocabulary for your problem domain may be hard, one may simply not exist.  Adopting something like Atom Feeds or XHTML may seem artificial or awkward (yet often are the best choices you have).
Grails or Rails make it easy to spill out XML or JSON, but this will not be any standard vocabulary and your resources will not be connected.

Even much simpler problem of assuring that error messages are served in a format expected by the clients are often surprisingly easy to overlook and may not so easy to implement.

Statelessness.
REST has no place for cookies, session objects, etc. Simply put: don't claim your app is RESTful if you store server state between HTTP requests.  Hypermedia is the engine of application state in REST.

I may be opinionated on this but to me it is not just about REST:  if you programming web app and use session object, you should rethink your design.  But then since people use server side state on web apps a lot, they must be finding this technique convenient and the benefits of being stateless not worth the extra effort to them. 

My personal opinion is that a possible exception to this rule is use of some standard security infrastructure (like Spring Security) which may have stateful implementation and you have no control over it.  This still would violate REST, but you may have not much choice.

POST is the worst of the 6 verbs.
I you can avoid using it you should.  But that is obviously not easy.
I am not elaborating on this one ... go and read the book ;)

Connectedness.
If the client has to construct URLs then the server is not RESTful.  Ability to discover URLs is what differentiates REST from API.
I wrote a bit about it in my previous post.  This is the hardest thing to do right and will impact your decisions on representation formats. This topic is out of scope for this post.

My next post will focus on the coexistence of Web App and REST

No comments:

Post a Comment