(Personally, I think it would be healthier if we worked out the wrinkles in REST by writing lots of code rather than writing lots of blog entries, but blog entries are easier, and XML people have never been shy about pontificating, so here goes …)
Joe Gregorio has an excellent article on REST at XML.com, and I recommend that anyone interested in building an XML data app with REST rather than RPC (Web Services, etc.) take a look at it. However, one point in the article jumped out at me. Joe mapped CRUD to the standard HTTP verbs like this:
CRUD |
HTTP |
Create |
POST |
Retrieve |
GET |
Update |
PUT |
Delete |
DELETE |
Personally, I’ve always seen the mapping more like this:
CRUD |
HTTP |
Create |
PUT |
Retrieve |
GET |
Update |
PUT |
Delete |
DELETE |
In other words, PUT does double duty for both Create and Update. Of course, the sad point is that almost no actual REST applications work this way — most of them are read-only, so GET is the only verb that counts, and when they do allow updating information, they do not do it by sending an entire resource representation (i.e. XML file) via PUT.
What about POST?
I think there are actually two roles that POST can play in a data application:
- Partial, in-place updates (i.e. send just pieces of changed information, rather than a whole resource).
- Actions (i.e. buy a book).
For example, consider this resource representation (fancy REST talk for “file”) using POX:
<pet-record xml:base="http://www.example.org/pets/lassie.xml" xmlns:xlink="http://www.w3.org/1999/xlink">
<name>Lassie</name>
<gender>f</gender>
<dame xlink:href="spot.xml">Spot</dame>
<sire xlink:href="jenny.xml">Jenny</sire>
<offspring xlink:href="marmaduke.xml">Marmaduke</offspring>
<offspring xlink:href="snoopy.xml">Snoopy</offspring>
</pet-record>
Now, let’s say that Lassie has another puppy. Using REST, there are two obvious ways to update this information. The first is to download the XML file (using HTTP GET), add an extra offspring element, then upload the modified file (using HTTP PUT):
<pet-record xml:base="http://www.example.org/pets/lassie.xml" xmlns:xlink="http://www.w3.org/1999/xlink">
<name>Lassie</name>
<gender>f</gender>
<dame xlink:href="spot.xml">Spot</dame>
<sire xlink:href="jenny.xml">Jenny</sire>
<offspring xlink:href="marmaduke.xml">Marmaduke</offspring>
<offspring xlink:href="snoopy.xml">Snoopy</offspring>
<offspring xlink:href="clifford.xml">Clifford</offspring>
</pet-record>
The second option is simply to send the REST server a message that it should add an extra offspring, by using HTTP POST to a URL like http://www.example.org/pets/updates/add-offspring
and using parameters to identify sire or dame and offspring. I don’t know that it’s possible to say that either of these approaches is better; obviously, the POST approach would make more sense for very large resources.
The other use of POST would be to execute options that do not have an obvious correspondence with resource representations/files. A good example would be posting to a URL http://www.example.org/pets/actions/buy
including parameters describing the pet you want to buy (i.e. the URL of the pet’s XML file — we’re RESTful, after all) and the price you are willing to pay.
The one use I don’t see for POST is uploading entire XML files, except as a way to work around firewalls that block PUT. Maybe we should fix the firewalls, or maybe we’ll just have to learn to live with this (ab)use of POST as a practical necessity for making REST work with the current web infrastructure.