As some of you undoubtedly know, I'm writing a thing called txYoga, which is a REST framework for Twisted.
The fundamental operations in this post are CRUD:
- Creating elements
- Retrieving them
- Updating them
- Deleting them
Now, retrieving is obvious: send a GET request to the element. Getting rid of them is too: same thing, but a DELETE. Updates are done using PUT to the element. Creating elements, though, is a bit more ambiguous:
- If the client knows the complete path to the element (so, particularly the final part of the new element's URI), it PUTs to that URI (for which there is currently no element).
- If the client doesn't know or care, it POSTs to the collection. The collection creates the element, and probably returns the URL under which the new element is available.
One of the fundamental differences between POST and PUT is that PUT is idempotent, but POST is not. If you send me the same PUT request once, twice or ten times, you'll end up with the same state. POSTing to the collection might work once (or pretty much indefinitely, if you're producing objects with an UUID identifier for example).
This is because in txYoga, each element has exactly one identifying attribute (which is the thing that's used to access the element). That's what makes PUT feels so awkward: what you're putting contains the information to decide what the name of the object is (since it has to have the identifying attribute), but the object doesn't know what name it's going to be put under (since that name only exists after the object is created), so you have to repeat yourself. With POST, you don't really care.
Additionally, you'd be using the same thing for updating and creating new elements, which I guess sort-of makes sense, but reminds me of Perl's autovivification and not in a good way.
The question is: should I support both PUT and POST for creating elements? On the one hand, There should be one-- and preferably only one --obvious way to do it. On the other, this is what REST pretty much does -- and practicality beats purity (although this isn't very practical for me...).