The Background (the long version)…
Whilst experimenting with RESTful web-services, my natural inclination has been to explore the mechanics of the protocol level interactions associated with resource state changes. The majority of mainstrean REST examples relate to manipulation of resources via representations obtainable through atomic operations (i.e. DBMS CRUD, File-system CRUD, etc). However the context I am exploring has to deal with the harsh reality of a single resource operation (i.e. POSTing a request to generate a new resource) not being atomic, but instead requiring complex background processing prior to creation of an addressable representation to maintain the uniform RESTful interface.
So in simple terms I issue a request ‘POST http://www.domain.com/resource-type’ and attach an entity body conforming to the basic content requirement of this particular operation on the resource-type. The protocol mandates that on successful completion of the POST operation I return a ‘201 Created’ response, with a ‘Location: http://www.domain.com/resource-type/unique-id’ as the addressable resource instance from this point onwards.
This is absolutely clear. However when applying RESTful principles to a complex machine wherein I have no control over the allocation of the primary keys (unique-id’s) which form part of the Location URI, then my RESTful presentation must interface with underlying resource implementations to fulfil processing contracts and deliver me the key and the representation I need to conclude my synchronous POST operation.
At this time I start looking for flexibility within the uniform interface. There is provision within the http protocol for me to use a ‘202 Accepted’ response to an incomplete resource operation. So then I begin looking for how that would fit into my RESTful presentation of a set of complex resources behind the resource oriented facade. So the scenario changes at this point, simply because I can now empower both my client and my RESTful server to have choices and make decisions about how to implement what would otherwise be a synchronous http interaction. Why?
Well as a client of an http endpoint, my resources are locked open for the duration of the server processing delay. If I have unpredictable load-levels (i.e. in a programamtic client) then I may wish to place a limit on the time I will leave my resources bound to a server which may not have a predictable response time. Similarly, as a server I may wish to govern the loading I accept, not by rejecting connections which risks leaving clients in an inconsistent state, but by providing a point of accountability in the application layer, while I go about implementing the requested operation. So – in simple terms I am looking to implement selective asynchronous working within a RESTful interface – maintining purity and uniformity in terms of rfc2616.
So if I rely on the client specifying a MAX_WAIT protocol header in the http headers, and I enable my RESTful server to make insightful decisions about requested wait times versus know processing times, then I have a situation where selective use of the ‘202 Accepted’ response can provide massive flexibility without overly impacting the clients (i.e. who ‘really’ gets irritated by traditional redirects these days? Redirects are almost a part of life, and they are accepted as they add value despite falling outside the basic GET/200 model) in terms of complexity.
The problem I have is the nature of the ‘Location:’ header I return with the ‘202 Accepted’ status?
The Question (the short version)…
So I request ‘POST http://www.domain.com/complex-resource’ with an associated entity-body, but I specify a WAIT_TIME of 0 implying I need immediate confirmation of acceptance so I can return at a later time to check completion. If I then get a 202-Accepted response from the server, what is the URI? Is it ‘Location: http://www.domain.com/operations/12345′ or is it ‘http://www.domain.com/complex-resource/12345’ ? In both examples, the ID of 12345 is a locally generated alias which the RESTful server can map to the real primary key returned from the back end implementation at some point in the future – but from a resource client perspective what am I expecting?
My preference is currently that the 202-Accepted alias Location should reflect the resource-type of the initial request for consistency, despite returning a temporary ID which will be redirected (i.e. 30x) automatically on creation of the true resource id. This means that as a client, I see no real impact to my uniform interface other than a redirect or moved-permanently response at some point in the future.
However there is an alternative, strong, argument for the use of an entirely distinct resource-type such as ‘operations’ to make it 100% clear that your requested resource operation is not currently fulfilled, and you have a reference point which enables you to check the status of the request at you leisure. When that operation completes your operation representation includes the fully-qualified URI to your requested resource. You then pick that and use it from that point…as an explicit action versus an implicit (possibly subversive redirect).
Question is – which is most appropriate? On the fence at the moment having implemented both….