Founder and CTO at MindTouch, Inc.
From Nic Ferrier:
A common pattern espoused here is the POST, then PUT. It works really
well for transactional models.
You POST to create a transaction resource... and then PUT it's state
to it (perhaps repeatedly).
From Andrew Wahbe:
I have to say that I agree with Elliotte Rusty Harold's blog post that
PUT is not the same thing as UPDATE
(http://cafe.elharo.com/web/put-is-not-update/). The SQL analogy that
is so prevalent in REST 101 tutorials hurt me more than the helped me
as I was coming up to speed. It's just confusing.
I think a better alias for PUT is "SET". Its connotations fit the
method much better and pair it up nicely with GET -- programmers
usually think of accessor methods when they hear "get" and "set". Its
not a perfect analogy as an accessor method usually isn't setting or
getting the full object. But if you instead think of your resource
space as the "object" then accessors getX() or setX() on member X map
to the semantics of GET and PUT on resource X. If you also add that X
might start out as NULL or undefined until you call setX() then you've
pretty much covered it.
However, if you pair GET and PUT in this way, it leaves you with POST
and DELETE. With the CRUD analogy, you have CREATE and DELETE --
another great pair.
But POST is so much more than CREATE. In both the HTTP RFC and common
(restful) practice, POST is generalized to a transformation of the
target resource and its subordinate resource space. However, this
transformation is usually some sort of augmentation of the resource
and/or its subordinates. For example, you are creating a new resource,
or appending information to the target resource, etc. The examples in
the definition of POST all have this flavor. Even when a POST just
submits something for processing, you've added the something to an
invisible queue of work.
Unfortunately, the lowly DELETE method is not such a great match for
the almighty POST. It deletes the target resource... and that's about
it. It makes you wonder: should DELETE be given a shot of steroids? Or
do we need a new method to represent a general reduction of the
resource and/or subordinates?
This issue sort of jumps out at you when you consider implementing a
REST interface to some sort of queue. You immediately arrive at
POSTing to the queue resource to enqueue data (e.g. POST to
http://example.com/queue). But dequeuing data, on the other hand, is
not so obvious. One solution is proposed here:
http://www.xml.com/pub/a/2005/01/05/restful.html But as pointed out in
the comments, there seems to be a race-condition issue with multiple
consumers. The reply to the comment proposes a work around, but unless
I'm mistaken uses an unsafe version of GET as it essentially dequeues
data in the read. Regardless of the specific issues though --
dequeuing is certainly not a straight forward as enqueuing.
Perhaps DELETE can be extended to make this easier. Allowing DELETE to
return the contents of the delete resource helps. This isn't strictly
forbidden by HTTP as the DELETE response can have a body. But ideally
you also want to be able to target the operation on a resource that
represents the head of the queue rather than the resource to be
deleted (e.g. http://example.com/queue/head). This saves consumers
from having to co-ordinate ownership of dequeued resources before they
DELETE them. So you'd want http://example.com/queue/head to be an
alias for the resource currently at the front of the queue; when you
DELETE the alias, you actually delete the resource at the front of the
queue and the alias stays intact. But that sort of behavior is not
allowed by DELETE right now -- its not idempotent.
Another possibility is to add a new method, say PULL, that performs
some reduction transformation on the resource and its subordinates and
returns the removed data. A 2xx "Deleted" response code could be added
to indicate when the method resulted in a resource being deleted. The
Location header could name the victim. With this method, you add to
the queue with a POST to http://example.com/queue and remove from the
queue with a PULL from the same resource.
Finally, one could just say that POST is a transformation that is
typically an augmentation -- but not always. That let's you POST to
http://example.com/queue/tail to enqueue and POST to
http://example.com/queue/head to dequeue.
Does anyone else see this as a problem? This lack of symmetry does
seem to be related to a lot of the headaches I come across when trying
to do things RESTfully. Are there alternative solutions that I'm missing?