REST’s uniform interface constraint requires the operations that can be invoked on a resource to be generic, meaning that the applicability of an operation must not depend on the actual nature of the target resource. The uniform interface does not prohibit additional methods to be defined but requires any extension method to be generic. PATCH or MONITOR (slide 16) for example are valid extensions, while ORDER or PAY are not.
Our OO-biased brains are trained to think in terms of classes and associated operations (Cart.order()) and it apparently takes a considerable amount of time for our brains to re-wire and think in terms of transferring representations to modify resource state.
As a result, people are tempted to come up with ways to map non-uniform operations onto HTTP’s uniform interface. One offspring of such endeavor is the REST anti pattern of Action Resources.
I have not tracked it back to its origin, but the general form goes something like this:
Given an operation foo(), define a link semantic ‘foo’ that enables the server to tell the client what the URI is of ‘the foo-action resource of some other resource R. Knowing the foo-action resource Rfoo, the client would then be able to invoke the foo() operation on R by means of an empty POST to Rfoo:
Find foo-action resource of R:
HEAD /items/56 200 Ok Link: </items/56/foo>;rel=foo
Invoke foo() on R:
POST /items/56/foo Content-Length: 0 204 No Content
So, why am I calling it an anti pattern?
Action resources are an anti pattern because the approach violates REST’s self descriptive messages constraint. How so? Because the meaning of the POST request depends on resource state at the time the client learned that /items/56/foo is the foo-action resource of /items/56. There is nothing in the request that allows the server to understand the actual intention of the client at the time the server handles the POST request.
Suppose the client issues the above HEAD request at time T1, the server replies at T2 and the client receives the response at T3. By the time T4 the client sends the POST request to the action resource (and T5 when the server actually receives it) the server might have changed and is now looking at the POST with the empty body which translates to the client intention of telling the resource /items/56/foo to process this [empty body].
The server does not know that the request semantics depend on the server state at T2 when the server created the HEAD response and therefore cannot detect any mismatch between client intention and its own interpretation.
Pure operations do exist. What do you do then? Get slapped by the REST police and lose the “REST” brand?
Just design the messages to communicate the user’s intent. For example, instead of doing something like POST [empty] /carts/65/order POST.. to /order-processor. In the former request the meaning is just ‘order whatever you currently perceive /carts/65 to be’ while the latter contains, right *in* the message that the user wants to order a bunch of particular items.
@jan – in the latter case, what would be the mechanism by which the system would creates an association between a submitted order and the corresponding cart?
I’m not convinced that this matters all that much, and you can still drive the former via hypermedia so evolveability can be maintained.
@Mike: it does not need to. At least not for the ordering itself. I guess it would compare the order to the user’s cart (based on logged-in user ID) and empty the cart afterwards.
That seems like it would be unnecessarily convoluted and flakey.
Perhaps it might make more sense to create those orders with a very simple representation containing a URI to the cart?
POST /order-processor
But then, of course, we’re back to the meaning of ‘order whatever you currently perceive /carts/65 to be’ – and it’s probably much easier to “just” use an action resource.
The example got stripped, it was meant to look like this:
POST /order-processor
<order>
<link rel=”cart” uri=”/carts/65″ />
</order>
[...] Why ‘Action Resources’ are a REST Anti Pattern [...]
You might also want to see: http://alandean.blogspot.com/2008/11/what-restful-basket-checkout-might-look.html
Interesting article Jan. But unfortunately I didn’t get you second examples right (/order-processor) … did you mean that the POST to this resource contains a list of all items being part of /carts/65? Would be very glad if you could clarify this for me. :)
However I think @Mike’s suggestion basically is an equivalent to the Anti Pattern Jan described in this post. But this time “/carts/65″ is the possibly changed/outdated resource.
I personally think that POST [list-of-cart-items] /orders would be a good solution, because it’s self-descriptive and follows the a resource oriented approach.
Hi Tony,
yes, the second example should list the items explicitly, to make it clear, right in the message, what the client intends to order. This could well be a replay of the cart content, yes.
Jan