Saturday, March 19, 2005

RESTful coding standards

In AJAX Considered Harmful Sam Ruby starts to lay out a set of useful coding standards for REST. He addresses Encoding and Idempotency, however going a little further has helped me. I have tried to apply the KISS principal and be a minimalist i.e. only add layers of complexity when you need them


Most use cases I have come across can be reduced to a CRUD interface (and yes there are exceptions, and exceptions prove the rule). The starting point is some standard naming conventions to create some degree of consistency for users for example:



  • Create POST to http://xml.domain.com/resource/Create

  • Read GET from http://xml.domain.com/resource?QueryString

  • Update POST to http://xml.domain.com/resource/Update

  • Delete POST to http://xml.domain.com/resource/Delete


The other issue is how to pass arguments and results back and forth. Some decisions are obvious, GET always passes a query string and the return data is always XML both using UTF8. I always have issues with POST though for invocations I recommend using XML always as it is hard on a user to have to switch between POST form parameters and XML for different methods. If XML is always used it keeps everything consistent. However when a delete method only requires a single key it is very tempting to just pass form parameter or even just do a GET with a query string. So far I have stayed with consistency - I would be interested in other opinions.


The other of standardization that helps is error returns, SOAP Faults are a good idea that REST can easily adopt. With a CRUD interface there are a simple set of standard errors that can be defined that come back with a HTTP 500 status code:


  • Create: Item Already Exists User has no permissions ...

  • Read: Item Does not Exist User has no permissions ....

  • Update: Item Does not Exist Item Locked User has no permissions ...

  • Delete: Item Does not Exist Item Locked User has no permissions ....


A simple REST Fault schema can be used to always return the same format such that common utility code can be created to handle errors in a uniform way. For errors to return permissions errors there needs to be the idea of identity which requires authentication


For authentication the lowest common denominator seems to work most of the time - interested to hear about real cases where it does not. If the request is over HTTPS and the authentication is HTTP-Auth then we have pretty good security. One step further would be to PGP the message but that would only be needed where the message needed to be highly secure and it traveled over unsecured pipes before and/or beyond the HTTPS stream.


I would be interested in feedback and extensions to this as it would be nice to have a consistent pattern for programming REST interfaces. The consistent pattern would enable us all to build interfaces faster and learn to use the work of others faster and easier.

4 comments:

Mark Baker said...

John, I think you're missing the point ... or else I'm not getting what you mean. But when you say "Create POST to http://xml.domain.com/resource/Create", are you saying that in order to create a resource, you'd POST to that URI? If so, that's not consistent with REST (at least when viewed in the context of the rest of your suggested operations/URIs).

To do those things RESTfully, I'd do this;

Create (when client knows the URI); PUT uri-of-resource
Create (when client doesn't know the URI); POST uri-of-container-resource -> 201 response with Location header pointing to uri-of-resource
Read; GET uri-of-resource
Update; PUT uri-of-resource
Delete; DELETE uri-of-resource

Mark Baker said...

Oh, and HTTP already has standardized faults, e.g. 401 for not authorized, 404 for "does not exist", etc..

John McDowall said...

Mark,

Perhaps we are talking at cross purposes. To help explain my pov I will try an example. If the "resource" is a service that handles purchase orders. Then the "create" (I think I prefer "add") method takes an XML message that adds another Purchase Order to the service. The message is completely self describing so no other information should be required. So I am not creating the resource but adding a new instance to the service.
I struggle with PUT and DELETE not because I do not agree with their usage but rather most APIs I am seeing are nearly all "Low REST" to quote Nelson Minar. Have you seen any good public "high REST" APIs?

John McDowall said...

and the standardized faults are for HTTP, if the user is authorized to access the resource and it exists the a 401 or 404 are not appropriate. To continue the example if I want to update a Purchase Order I am authenticated successfully and the resource exists but the updated purchase order I send does not already exist then I want a specific message level error message. Similarly for not authorized - I may not be permissioned to change a specific Purchase Order which is different from not being authenticated.