Reuse is often a good thing, but only as long as the mismatch between your needs and the functionality offered by the tool is relatively small. There’s definitely a lot of merit in reusing the HTTP verbs as “REST verbs”, but there are many drawbacks too. The general confusion about when to use POST or PUT is just one example, but one that can be overcome. There are other and more serious problems with using HTTP verbs as REST verbs.
There are two pieces of evidence that prove there’s a big problem with the HTTP verbs, especially when applied to RESTful webservices. The first piece is the section “Relationship between URL and HTTP Methods” on the Wikipedia page about REST, and comparable sections on other websites and tutorials. In the case of Wikipedia, there’s a table that tries to explain how the four main HTTP verbs GET, POST, PUT and DELETE should be used in the basic use cases of a RESTful API. Even though the table does a good job at explaining how the four verbs should be used, most novices at REST will get it wrong and make lots of errors in their first APIs. I know I did, and I’ve seen a lot of other people do it too.
In particular the use of the verbs PUT and POST creates a lot of confusion. A search on Google with the keywords REST PUT POST is my second piece of evidence that there’s a big problem with the HTTP verbs: it produces (at the time of this writing) about 491 million results, with many of the top results being links to questions on discussion forums about when to use PUT and POST.
I don’t know how much confusion there was about PUT and POST back in the days when HTTP verbs were just HTTP verbs. But my feeling is that it didn’t matter much, because it didn’t make much of a difference when someone mixed the two up. As long as the server was able to receive and process the HTML form, (almost) nobody cared whether it was done using a PUT or a POST. Nobody published HTTP APIs anyway, so you would have to be doing web scraping against a web site to find such errors. And even then you probably wouldn’t care much.
That changed with the advent of REST. Suddenly, people started to publish their REST APIs, and using the correct HTTP verb became a much larger issue as it carried part of the semantics of the methods in the API. Mixing two verbs up, or using one of them incorrectly in one way or another suddenly meant that your REST API became harder to read and harder to understand. That’s something different than forcing your users to submit HTML forms with the wrong HTTP method, as long as it happens under the hood anyway. What worked fine –or shall we say, at least “good enough”– for HTTP, became a big issue in REST.
One can wonder what would have happened if REST had created its own set of verbs, instead of reusing the HTTP verbs. Would we have ended up the same way, with lots of confusion between the REST version of PUT, and the REST version of POST? Or would we have found an alternative set of verbs that’s much easier to understand? An approach closer to CRUD would certainly have solved the PUT versus POST confusion, but then again, maybe CRUD would have generated another set of problems that’s even bigger?
Maybe a design from scratch would have resulted in a more extensible approach? Remember the example from my previous article, where I discussed what would be the correct HTTP verb for a one-time download. Being able to define a new verb (say, ONE-TIME-GET, or GET-AND-DELETE) with its own meaning would have been a cleaner solution than reusing GET. But doing so creates its own problems. In theory, you can extend HTTP with your own verbs, but often that’s a very risky business. Anybody who has tried to use one of the other HTTP verbs than GET, PUT, POST and DELETE in a REST API, like e.g. PATCH, knows how difficult that can be. That’s especially true when there are proxies and firewalls between your client and your server. I’ve tried it a couple of times, and I’m pretty sure I’d rather go for a slightly off GET before I would try to implement a ONE-TIME-GET.
The consequence is that when you’re designing RESTful webservices, the methods in your domain model have a tendency to converge to or at least include equivalents of GET, PUT, POST and DELETE. From a domain-driven design (DDD) perspective, that’s a bit of pitty, because you’d rather avoid such external forces on your design. The section “Relationships between Resources” on page 228 of Leonhard Richardson and Sam Ruby’s book RESTful Web Services is a good example of what this can lead to.
Still, I’m glad REST ended up using the HTTP verbs, in spite of the confusion around PUT and POST. After all, the HTTP verbs do have a well-defined and widely accepted meaning, and any other set of verbs would probably have brought its own confusion anyway. But more importantly: because of the reuse of the HTTP verbs, and the HTTP protocol in general, REST works well wherever HTTP works well. And it does handle 99.99% of the cases I’ve come across pretty well.