Draft 5 of REST-* messaging talked about iterating on the reliable posting protocol. Recently, I was arguing with Jan Algermissen on a completely unrelated subject. As a result of this conversation, I ended up re-reading Roy’s post on hypermedia for the 4th time in 2 years. Re-reading Roy’s blog got me thinking a bit about improving the message posting protocol of REST-* Messaging so that it is driven more by in-band information, rather than out-of-band information.
Firstly, I want to remove the post-message-once and post-message link relationships. Instead, a destination resource would only publish the create-next link. When a client wants to post a message to a queue or topic, it will use this link to create a new message resource on the server. The type of this link would be “*/*” meaning it accepts any media type.
The key change to the protocol would be for the client to be aware that responses to creating messages through a create-next link may contain a new create-next links. The client is encouraged to use these new, on-the-fly, create-next links to post additional messages to the topic or queue. An important point of this change is that the server is not required to send a create-next link with its responses. How, and if, the server protects itself from duplicate message posting is up to the server.
So how could the server protect itself from duplicate message posting? One implementation could be that the server returns a 307 response code, “Temporary Redirect” for the initial POST to the static top-level create-next link published by the destination resource. This 307 requires the client to re-POST the request to a URL contained in a response Location header as defined by the HTTP 1.1 specification. The Location header would point to a one-off URL (like the previous protocol defined in Draft 5). If a network failure happens, then the client re-POSTs to this URL. If the messages was previously successfully processed by the server, the server would respond with a 405, Method Not Allowed. If no network failure happens on the re-POST from the 307 redirection, then the server would just return a success code. In either response, the server would also return a new create-next link as a Link header within the response. The client would use this new create-next link to post new messages. Subsequent posts to these new links would not have to go through the re-direct protocol because they would be newly generated one-off URLs.
I have been reading a bit that some weird or undesirable behavior may be experience with some user agents when using 307 and POST/PUT. So, I think that if the REST-* Messaging specification leaves it undefined how a server implementation handles the initial response of a duplicate-message protection protocol, we can let it evolve on its own. The key here is that the client should be encouraged to look within the response for new create-next links even from error responses. For example, if instead of 307, the initial POST return a 415, Preconditions Failed and that error response contained a create-next link header, the client should use that link to re-post the request. NOTE! I think 307 is probably the best implementation, but maybe its best to give flexibility to implementors.
Keep the *-batch links
I still want to have separate links for submitting batches of messages. Specifically rename post-batch to create-next-batch (and remove post-batch-once). I want the distinction so that the server knows that it is receiving a collection of messages vs. the server just forwarding a message to message consumers that just happens to be a collection media type.