Stefan Tilkov points to a recent work by Joe Gregorio: RESTify Day Trader
He highlight's Joe's suggestion to use PUT to reliably create server-side state. In particular, to lodge a purchase order. I have been suggesting this kind of approach for a while, but I have issues with Joe's specifics. I am particularly focused on how automated REST clients and services interact, so I take things a little beyond whatever works in the browser. I have issues with Joe's POST precursor and 303 response.
I'm not sure the POST used by Joe is entirely necessary. PUT is allowed to create the resource at the request URI, so creating it using a POST in an earlier request is not strictly required. The only thing necessary is for the client to discover or construct the url of the order that it is about to submit. I suggest either a non-cacheable GET that returns a different URL each time, or construction of the url with a client-supplied guid will be appropriate. Which is the most appropriate will depend on the exact situation.
Preferred approach:
>> GET https://example.com/orderForm (repeat if necessary) << 200 OK, form with https://example.com/order/1000 as submit element (non-cacheable, with a different submit url for each request) >> PUT https://example.com/order/1000 (data) (repeat if necessary)
Fallback approach:
>> PUT https://example.com/orders?guid=client-supplied-guid (data) (repeat if necessary)
I also wonder about the use of 303. rfc2616 is clear:
"The new URI is not a substitute reference for the originally requested resource"
It isn't appropriate for a client to take this url and use it as the url of its order. The most it should do is retrieve the response to its PUT request using an additional GET request.
There is no need to "move" the resource to a new URL. The URL is its identity. This identity should not include the state of the order, and the identity of this resource should not change. The URL that the client issued the PUT to should be the one it continues to interact with for GET or PUT transactions with the order.
The move also puts stress on PUT's idempotency: If the client issues the request again after the move has occured, is it going to issue an additional order? Will it get a 410 Gone response? The former is a bug, while the latter is difficult to interpret. Did the server reject the request, or was it successful? 410 is unavoidable if the resource is DELETED before the client finishes repeating its requests, however in my view it should be an exceptional rather than a common case.
Benjamin.