The Mine! Project

open source project for online data and relationships logistics

A method for massively cutting UPDATE/HTTP-PUT methods in complex Rest APIs

TAGS: None

I like the ReST interface, but I am not fundamentalist about it.

Most of the objects in the Mine implementation are “Things” – ie: a series of key=value pairs which are bundled together under a numeric identifier, which have a Class and associated methods that operate on them.

For reasons of security and sheer implementability, “Things” may not be updated under the ReST CRUD scheme; to recap ReST you are allowed four “CRUD” operations against a URL which represents an object:

  • Create (a new object, in a directory, say)
  • Read (an existing object)
  • Update (an existing object)
  • Delete (an existing object)

So for example:

  • CREATE (key=value …) /api/object.xml
    -> new object populated with keys/values, id = 42
  • READ /api/object/42.xml
    -> a bunch of key=value pairs in XML
  • READ /api/object/42.json
    -> a bunch of key=value pairs in JSON
  • DELETE /api/object/42.xml
    -> deletes object 42, status returned in XML

…but the one that gives problems is UPDATE since the presumption is that you will atomically replace an old Thing with a new thing, much as:

mv new.jpg current.jpg

…might work in a filesystem; you are swapping one bunch of bytes for another one; but Things are complex structures with some bits you can poke, and other bits you cannot. Merely splatting them with replacement data would be painful.

Amongst the other problems with this is that “Update” is usually mapped to the HTTP-PUT method, which is badly implemented in web browsers and actually I think is below the tipping point – ie: it’s so badly implemented that ReSTful people work around it rather than get it fixed. Standard Perl::CGI for instance, does not support it.

The way I have gotten around this is slight but elegant piece of doublethink; I have implemented a ReST interface atop each Thing object, to access its key=value pairs:

  • READ /api/object/42/key/keyName.xml
    -> value associated with keyName for object 42, in XML
  • READ /api/object/42/key/keyName.json
    -> value associated with keyName for object 42, in JSON
  • DELETE /api/object/42/key/keyName.xml
    -> unset keyName in object 42, status in XML

…and then realising that object 42 now must exist for this trick to work at all, and that there is no point in having CREATE “choose” a key name for you – predefined variable names do not fit the ReST-CREATE model – then the key/CREATE and key/UPDATE operations are otherwise functionally identical (ie: they poke the values of keys) and therefore the latter can be dropped. Also key/CREATE is cooler, since it can poke multiple keys at the same time.

Further, that means key/CREATE is functionally identical to Thing/UPDATE so that can be dropped, too.

So all that is necessary is to mentally “rebrand” the key/CREATE operation as the Thing/UPDATE operation, and a whole pile of UPDATE operations go out of the window.

So now there is only 1 ReST-UPDATE operation that remains in the Mine – down from 11 – and that is the “update of auxilliary data”, for example replacing one JPEG that is associated with object 42, with a different JPEG.

To me this is a straight swap of one blog of data for another one, and so should remain as a ReST-UPDATE; but anywhere else that I have a ReST interface onto complex objects, I shall in future consider very carefully before implementing a UPDATE method.

TAGS: None

5 Responses to “A method for massively cutting UPDATE/HTTP-PUT methods in complex Rest APIs”


  1. dropsafe : A method for massively cutting UPDATE/HTTP-PUT methods in complex Rest APIs
    on Jan 16th, 2009
    @ 9:05 am

    [...] The Mine! project » A method for massively cutting UPDATE/HTTP-PUT methods in complex Rest APIs [...]


  2. Ben
    on Jan 16th, 2009
    @ 11:44 pm

    Thanks to the unstructured nature of the content of an HTTP POST you can aggregate updates of an object’s values into a single request aimed at the object instead of the individual keys by using an xml/json object in an HTTP POST (or even just a set of key-value pairs!) and have a ReSTful server figure out where to apply them. That’s not an abuse of the ReST concept as you’re still only using the CRUD operations, just on larger objects than just strings and numbers.

    ReST is a nice design direction – we’ve been doing it for a couple of years (at least our non-purist form of it at my current place of work) and it’s proved to be flexible enough to stand up to some quite diverse requirements (and it suits ExtJS single-page applications!). My only regret is that we chose to specify the representation as an additional parameter in the request (/api/object/42?rep=xml), rather than as the dot extension (/api/object/42.xml) as you have it.


  3. Ben
    on Jan 16th, 2009
    @ 11:47 pm

    p.s. if you’re using Java on the server-side look at open-source products like XStream (xstream.codehaus.org) for tools that can help with simple de-serialization of XML without the overhead of SOAP.


  4. PJ
    on Mar 2nd, 2009
    @ 6:56 pm

    Some thoughts:

    * the /key/ bit seems redundant. What’ s wrong with just /42/keyName.xxx ?

    * Consider implementing UPDATE for aggregations anyway, if it’s not too difficult. It will likely be useful to be able to atomically UPDATE a whole group of data in one swell foop, instead of having to individually set all those smaller pieces.


  5. alecm
    on Mar 2nd, 2009
    @ 9:40 pm

    Hi PJ – thanks for the input

    >* the /key/ bit seems redundant. What’ s wrong with just /42/keyName.xxx ?

    Clashes with other URL/operations in the same space, and I don’t want to get into parsing a token and then guessing what it meant to imply and/or having to forbid certain keynames / parameter names because they clash with API calls…

    Love the batch-update point, I was wondering about that and you’ve helped me decide.

    - alec

Leave a Reply

© 2009 The Mine! Project. All Rights Reserved.

This blog is powered by Wordpress and Magatheme by Bryan Helmig.