Let’s start by looking at our approaches to doing a CRUD on a server and forging some Urls to analyze. The first approach (let’s call it To) is to use the appropriate HTTP verbs:
GET http://www.example.com/somepath/resource.txt
PUT http://www.example.com/somepath/resource.txt
DELETE http://www.example.com/somepath/resource.txt
PATCH http://www.example.com/somepath/resource.txt
The second approach (B) is to use only GET and POST and place verbs in Urls:
GET http://www.example.com/somepath/resource.txt
POST http://www.example.com/somepath/resource.txt/put
POST http://www.example.com/somepath/resource.txt/delete
POST http://www.example.com/somepath/resource.txt/patch
The third approach (C) is to use only GET and POST and set form fields in the POST:
GET http://www.example.com/somepath/resource.txt
POST http://www.example.com/somepath/resource.txt
action=put&content=...
POST http://www.example.com/somepath/resource.txt
action=delete
POST http://www.example.com/somepath/resource.txt
action=patch&data=...
Now, let’s look at the advantages of the To on approaches B and C:
Advantage 1: All actions have the same URL and therefore they all clearly refer to actions on the same resource. If you have uploaded a feature with PUT, you are expected to get the same feature when using GET, change it with PATCH and destroy it with DELETE.
Advantage 2: PUT, DELETE and PATCH are idempotent, but POST is not. POST requests are not cached and generally cannot be repeated, unlike with PUT, DELETE and PATCH. But in the case where the POST represents a disguised PUT, DELETE or PATCH, they should be cacheable and repeatable, but the browser or some other agent will not know this, because the semantics are within the application and not in the protocol.
Advantage 3: The PUT, DELETE and PATCH methods are simpler pure than when encapsulated in disguised Posts. With PUT, for example, your request will contain as body only the resource you want to use to perform the upload and nothing else. If you use the POST instead, you will have to manage with multiple form fields and maybe with special rules for the enctype="multipart/form-data"
.
Advantage 4: The HTTP verb used makes it clear which action is being performed on the resource and therefore the expected behavior is well defined. If we are limited to GET and POST only, the URL will have to be changed (approach B) or you will be required to define custom form fields (approach C). The ideal is that the Urls were preserved and no custom field was needed.
Advantage 5: The processing of POST is not so well defined from the point of view of HTTP, as its semantics depends entirely on the application, unlike what happens with PUT, DELETE and PATCH. In HTTP, POST denotes only sending data to the server, but says nothing about how this data will be processed.
However the advantages of the To end there. Now that I have listed them, I will present the disadvantages and also deconstruct the advantages presented:
Disadvantage 6: Browsers only support forms with POST and GET actions. This is usually sufficient reason to force developers to abandon PUT and DELETE, since browsers will not be able to use them effectively and simply.
You can use the other methods via AJAX. But in forms you cannot because as explained by Ian Hickson PUT wouldn’t make sense because it doesn’t make sense to upload the content of a form, but just upload resources, which is not a form. DELETE makes no sense in forms because the DELETE method has no body and the form represents the body of the request. (link I used to find this information).
As a result, in the HTML5 specification only POST and GET are accepted as form submission methods:
The method
and formmethod
content Attributes are enumerated Attributes with the following Keywords and States:
The keyword get
, Mapping to the state GET, indicating the HTTP GET method.
The keyword post
, Mapping to the state POST, indicating the HTTP POST method.
The invalid value default for These Attributes is the GET state. The Missing value default for the method
attribute is also the GET state. (There is no Missing value default for the formmethod
attribute.)
Translating this into English:
The content of attributes method
and formmethod
sane listed attributes with the following keywords and states:
The keyword get
, mapping to the state GET, indicating the HTTP GET method.
The keyword post
, mapping to the state POST, indicating the HTTP POST method.
The assumed value when invalid for these attributes is the state GET. The assumed value when omitted for the attribute method
is also the state GET. (There is no assumed value when omitted for the attribute formmethod
.)
Thus, browsers only accept POST and GET in forms.
On the other hand, it is true that maybe this will change in the future, but for now it is so (link I used to find this information).
When/if browsers allow the use of PUT and DELETE in forms, the use of the back button of browsers can avail of the idempotency or cacheability of these methods and show more user-friendly messages than those that occur when trying toif you return to a page that is the result of a POST. This is a small possible future semantic advantage of the approach To, but it really is something perfectly dispensable in practice and although it can solve the problem of disadvantage 6 after the old browsers that do not implement it fall into disuse, it does not solve the problem of disadvantage 7 (see below) and does not give any other significant advantage to the To. When/if this is implemented, we may use PUT and DELETE in Apis, but what we are actually gaining in practice with this?
Note: Thank you to Marcelo Bonifazio for commenting that allowed me to find the reply from Bruno Augusto.
Deconstructing the Advantage 1:
Advantage 1 does not apply only to the To, but also for the approach C, since the URL does not change since the form parameters are not part of the URL.
Moreover, in practice this advantage is not significant over the approach B. So in this case the URL is not identical? What is the problem with this in practice? What happens is that in practice the difference of the Urls does not represent any kind of disadvantage.
Deconstructing the Advantage 2:
So what if the POST isn’t identical? If you have control of the server program and the client program you can implement any cache or repeat mechanism you want. If your client program is the web browser, then it could not cache or repeat the request anyway, because due to disadvantage 6 above, it can not use PUT, DELETE or PATCH by any means other than AJAX, and AJAX requests are neither cacheable nor repeatable (nor should they be).
Therefore, if you are using the browser, the idempotency of these methods means nothing. If on the other hand your client program is customized, then you can decide to cachear or repeat requests as you wish, even if it is a POST (just do it intelligently, caching only what you know is cacheable and just repeating what you know is repeatable). Or, your custom client program can completely ignore the questions of cache and request repetition since this will rarely meet any practical and real need in the case of PUT, DELETE or PATCH.
Deconstructing the advantage 3:
So what if the use of PUT, DELETE or PATCH disguised as POST is a little more complex than them pure? This extra complexity in practice is negligible and is a problem solved and overcome, and it is nothing that a little code on the server does not solve. Often such code is even implemented within frameworks, as with Ruby-on-Rails.
Drawback 7:
In the approach B We are required to modify the URL to specify which action is desired. Again, as explained when I deconstructed advantage 1, this is not usually a real problem in practice. For the approach C, the need to add form parameters also does not usually consist of real disadvantage.
However, in the To the action is specified in the HTTP method. And besides GET, we have PUT, DELETE and recently PATCH and only. We can use the Webdav to get some more methods (such as COPY, MOVE, LOCK and PROPFIND, among others), but we are limited to a predefined set of HTTP verbs, otherwise we are forced to use POST... Or is it not?
Imagine that according to the approach C We have Urls with POST like this:
POST http://www.example.com/somepath/resource.txt
action=banana
POST http://www.example.com/somepath/resource.txt
action=crazy
POST http://www.example.com/somepath/resource.txt
action=lol&type=huebr
POST http://www.example.com/somepath/resource.txt
action=hellokitty
So far so good. If we use the approach B instead, all right too:
POST http://www.example.com/somepath/resource.txt/banana
POST http://www.example.com/somepath/resource.txt/crazy
POST http://www.example.com/somepath/resource.txt/lol&type=huebr
POST http://www.example.com/somepath/resource.txt/hellokitty
Now let’s try to use the approach To in these cases:
BANANA http://www.example.com/somepath/resource.txt
CRAZY http://www.example.com/somepath/resource.txt
LOLHUEBR http://www.example.com/somepath/resource.txt
HELLOKITTY http://www.example.com/somepath/resource.txt
This is fucking ridiculous! OK that inventing custom HTTP methods takes some work and is something very unusual and not recommended to do without having thought about it very well, but it is not impossible (so much so that is what happens in the case of Webdav). This is feasible especially if you have control over both client and server implementation. However, this demonstrates that predefined HTTP verbs PUT, DELETE and PATCH, or even imported from well-known HTTP extensions such as Webdav will only make sense for a significantly small and simple set of actions that you can perform. For the other actions, the behavior and semantics are completely unrelated to the HTTP specification or that of any well-known HTTP extension and are completely on account of the application, and therefore ends up being better, simpler, easier and more practical to stick to the POST in these cases instead of inventing new crazy HTTP methods.
We can still try to save the approach To with something like that:
PUT http://www.example.com/somepath/resource.txt/banana
PUT http://www.example.com/somepath/resource.txt/crazy
PUT http://www.example.com/somepath/resource.txt/lol&type=huebr
PUT http://www.example.com/somepath/resource.txt/hellokitty
Or just that:
PUT http://www.example.com/somepath/resource.txt (Usa PUT como se fosse BANANA)
PATCH http://www.example.com/somepath/resource.txt (Usa PATCH como se fosse CRAZY)
COPY http://www.example.com/somepath/resource.txt (Usa COPY do WebDAV para LOL HUEBR)
MOVE http://www.example.com/somepath/resource.txt (Usa MOVE do WebDAV para Hello Kitty)
But that does not bring us any benefit, because it ends up throwing out the advantages of the approach To without getting rid of any of the disadvantages. In this bizarre we are only using arbitrary and semantically incorrect methods for stubbornness not to use the POST.
Someone might want to claim that the two forms above are scarecrows that I built from the approach To. Maybe this statement is even correct, but this does not change the fact that in many circumstances the predefined HTTP methods are insufficient and hence the best solution turns out to be to use the good old POST. Also, if the action to be performed is unrelated to what PUT, DELETE, PATCH or any particular HTTP extension (example: Webdav) propose. then I see no other chance to try (unsuccessfully) to save the approach To other than inventing new HTTP methods or forcing the use of existing HTTP methods even if inappropriate.
Deconstructing the advantages 4 and 5:
Due to disadvantage 7, in the approach To, the meaning of the action specified in the verb HTTP only applies to some particular cases, but when we bump into situations where no pre-http verbdefined if it applies, then we will either force the use of a semantically inappropriate HTTP method or we will have to invent new HTTP verbs and in both situations the well-specified semantics goes to the beauty, and it ends up being easier to use the POST (ie, abandon the approach To).
In addition, there is not much advantage in practice to have the action semantics well specified in the HTTP verb, except in the case of GET (and more basic HTTP methods like HEAD, OPTIONS and TRACE), but these are identical in all approaches. What semantics of using PUT and DELETE instead of an equivalent POST brings good and tangible in practice?
Completion: The advantages that the To presents are not significant and useful in practice, but its disadvantages in some cases are worrying and hinder the development of applications. On the other hand the disadvantages of the approaches B and C are of little relevance.
It is true that if you are developing an API that will be used by a custom client program or accessed via AJAX, you can use PUT and DELETE without problems and then avoid the 6 disadvantage of the approach To. However it is also true that you can also use the POST without problems and therefore the approach To will not offer any practical advantage over the approaches B and C.
As a result, I conclude that it’s simpler and easier to stick to the old GET and POST and use any of the approaches B or C. I convinced myself that there is no practical advantage of using PUT, DELETE or PATCH and that they are only a semantic preciousness, in fact these methods are superfluous and they can all be represented by POST.
It is also true that approaches can be combined. Nothing prevents you from having an API where some parties follow the approach To, others follow the approach B and others follow the C, and I can even think of a few reasons to do that (obviously this only applies to methods that are not based on GET). However, this will create an API that will have a Frankenstein style (but this is probably no problem in practice) and the parts of the API that use the approach To do not have many practical technical advantages for doing so, so that this choice will occur by mere whim or preciousness of the developer, or perhaps by some kind of artificial imposition coming from some specification, tool or framework. It is also perfectly possible to provide functionality redundantly, where the same functionality can be available through different approaches (which would be a polymorphic Frankenstein):
PUT http://www.example.com/somepath/resource.txt
POST http://www.example.com/somepath/resource.txt/put
In my personal experience, when I was designing some API through the approach To and bumped into disadvantage 7, even though without realizing it, I end up either using the POST (ie abandoning the approach To pure and creating a Frankenstein) or else I ended up forcing the use of an inappropriate HTTP method, and I believe the same happens with many other developers who try to follow the approach To.
But there’s nothing to save the approach To? Well, if you’re in a scenario where the idempotency of PUT and DELETE (or some other) methods is useful to you, it can make a difference. That is, if you are in a scenario where disadvantage 6 does not apply (especially if/when browsers accept them in forms, or you are using a custom client) and advantage 2 survives deconstruction attempt (that is, cacheability and repeatability exist in practice being well implemented, bringing real benefits to your case and are not or may not or should not be applied selectively to Posts)then you will have a relatively strong positive point in favor of using the PUT and DELETE methods. However in most cases that happen in practice, these situations do not apply or do not make any difference, and I can even visualize cases where the programmer designs the API and forgets that PUT and DELETE are idempotents and ends up using them improperly (and therefore should use POST same).
And now that I’ve finished my answer, let the flamewar debate in the comments. :)
I will vote to close because the question only allows empty answers :P
– Maniero
Close is with
POST
orDELETE
?– bfavaretto
The correct semantics should allow to be
CLOSE
:)– Maniero
Related: http://stackoverflow.com/questions/12142652/what-is-the-usefulness-of-put-and-delete-http-request-methods
– Victor Stafusa
@Victor So the correct one to close would be
PUT
, right? I doubt this site will do that (I tried to test it now, but I couldn’t figure it out). And what’s the problem with not doing it? Deep down, that’s my question.– bfavaretto
I’m trying to come up with an answer to your question, but the more I research, the more confused I get. A half hour ago I advocated the use of DELETE, PUT and other recently added methods such as PATCH and Webdav. However, the more I research on this, the more I become convinced that these methods seem to be superfluous and that at bottom it is nothing more than semantic preciousness without much practical meaning.
– Victor Stafusa
@Victor Yeah, I think something similar, but I hope someone will convince me otherwise :)
– bfavaretto
I think the question will only do the opposite :) I would also like to see good reasons for current use, but...
– Maniero
@Qmechanic73 This link there is POST vs GET only, that’s the easy part. What the bfavaretto is asking for is about PUT/DELETE vs POST.
– Victor Stafusa
I found this reply from @Bruno very interesting: http://answall.com/a/16930/14262
– MarceloBoni
Question of the hour :)
– Wallace Maxters