This is a single archived entry from Stefan Tilkov’s blog. For more up-to-date content, check out my author page at INNOQ, which has more information about me and also contains a list of published talks, podcasts, and articles. Or you can check out the full archive.

POSTing Reliably

Stefan Tilkov,

Peter Williams has a follow-up post in which he explains his original PUT-vs.-POST idea, which I understand now: The problem with PUT is that while it’s idempotent, it requires the client to know the URL to PUT to, so he suggested a PUT which returns a redirect to some URL created by the server. You then PUT your intended content to the URI returned, and only then the new resource is created.

I believe this is almost a good idea; it violates the original purpose of PUT, though — if I PUT to a URI, I don’t expect it to have different results each time I do so. So my suggestions would be a slightly different approach:

  1. POST to the URI and have it return 201 Created and the URI for the new resource in the Location: header.
  2. PUT the intended content to the URI, possibly repeatedly in case of error.

Of course this might end up generating “empty” resources, but this is true for the PUT suggestion, too.

Also worth pointing out: In a comment, Asbjørn Ulsberg writes:

What about using “ETag” for POST requests? It’s pretty easy for the client to hash the content into an ETag and then stuffing that into an header before it’s POSTed to the server. Consecutive POSTs of the same content would lead to the same ETag and the server could thus identify them as the same and not create two resources.

That sounds like a good idea, but I believe there’s no way ETags can be created on the client and then sent in a request header. The closest thing to what Asbjørn suggests is probably Yaron Goland’s SOA-Rity, which uses a client-generated message ID.

On April 8, 2007 10:19 PM, Bill de hOra said:

Once you combine the standard theorem for reliable transmission with HTTP’s assymetric design, you realise that a reliable over HTTP will take at least two requests. In that vein, think SOARity,POE and HTTPLR cover the solution space as far as HTTP goes. Anything else requires a two-way protocol, or an emulation of it in HTTP (as is done with BTF2.0).

The only other option is to dedup at the server, an approach for which I suspect you can’t define a protocol that is provably correct.