Why REST Sucks
vmrcre.org
vmrcre.org
Most people use GET for retrieval, POST to change system state and DELETE to delete an object. You might go crazy and experiment with PUT, or not, your choice.
As a team, you can establish some easy rules too (e.g. is it books/1 or books/book/1 to query a single book?).
Sure, REST is not going to answer every problem, but no standard ever does. Standards are meant as guidelines (esp. those related to naming conventions like REST). Have fun with it. Stop the hate.
I have always hoped to some day stumble across some madlad who scales a large production system on the back of DELETE
Although sadly browsers are starting to enforce the behaviors of verbs more and more...
Someone hurry up and get coding
That was....confusing on my first week.
I can't make this shit up if I tried.
At the risk of making an overly broad and offensive comment: amateurs discuss standards and semantics, professionals discuss resiliency and requirements.
Though if it’s just a todo app, it probably doesn’t matter. It matters slightly more when the resources you’re creating are things like “purchase orders” or “payments” or “shipments” or “hailing an Uber”.
Grab XMLHttpRequest and start returning different content types in the header and body. Depending what browser you are in you will start to see things go inconsistently sideways compared to the same actions on get or post
REST (like "object-oriented programming") is an ambiguous term that might refer to a reasonable and usable subset of behavior, or it might refer to a more extensive hypermedia-style design pattern.
REST, in the hypermedia sense, and in the sense of "the design principles behind HTTP in the first place", is a good way for a server to expose data to an intelligent human-guided client (i.e. a web browser). It doesn't do a lot for the API case, but it does a little and there's enough tooling to get you the rest of the way.
I usually don't even think of REST API's as RESTful. I think of them as RPCs that exchange JSON, except you define the RPC endpoint as an HTTP verb/URL pattern tuple, accept and treat as a contract the standards behind different verbs, use response codes for out-of-band metadata, and piggyback on all the tooling and infrastructure that people already built around serving HTTP to web browsers in the first place. If you want to strongly type your RPC, you can use OpenAPI. If you want to define your RPC ahead of time and then generate server and/or client code from a definition, you can use Swagger Codegen. There's enough adequate tooling that you don't necessarily need to resort to an actual RPC protocol, but that doesn't mean your REST API actually has to be RESTful in any meaningful way, or even that it should be.
A web-browser doesn't have any concept of REST; it only provides a sandbox for the client code which knows how to map paths to data (but pretty much never does so by means of any sort of introspection). Note that this isn't advocating against REST or in favor of RPC, just a neutral observation.
I'm specifically talking about the portion of rest that includes delivering actions with noun results, i.e. "Here's you comment record, if you want to edit it go to this URL, if you want to delete it here's a different one".
Also, I, personally, find that portion of REST to be silly. I like the organizational hints and guidelines, but the resource discovery seems far too pipe-dreamy to ever be built on a large scale.
How does that not describe a normal HTML page that has "edit" and "delete" links right next to the newly-created comment that it displays to you after you click the "reply" button on Hacker News?
I mean, it's not automatic discovery, because you're relying on a human being to read a rendered web page and know what the links mean, but it kind of qualifies if you expect that the client is partially made of meat.
Again, I think it's naive since while a lot of stuff has plain CRUD operations, there are entities in most webapps that have more complex operations. If I were writing an application that partially managed cutlery in a restaurant it's not clear where a "clean" verb on a fork would fit into REST and how a generic client would understand what significance "clean" has especially as it relates to future eat actions.
I have read through and understand the intent of the original RESTful system and I think there are some good and bad points. But, automatic discovery was definitely included in their vision of how it'd work, and actually seems like the center point TBH.
Hmm, that makes REST sound like it's pursuing similar ideas as the Semantic Web.
> Again, I think it's naive since while a lot of stuff has plain CRUD operations, there are entities in most webapps that have more complex operations. If I were writing an application that partially managed cutlery in a restaurant it's not clear where a "clean" verb on a fork would fit into REST and how a generic client would understand what significance "clean" has especially as it relates to future eat actions.
It isn't clear at all. It's possible, but in weird, hacky ways. Maybe when you're done with a fork, you DELETE the fork and then you can POST to /clean_forks/ to create a newly cleaned fork. And if you run out of forks to clean, it throws a 503 error. It's a terrible Kingdom of Nouns (https://steve-yegge.blogspot.com/2006/03/execution-in-kingdo...) but it might appeal to some people, for the same reasons that the original Kingdom of Nouns appealed to some people. After all, you get to feel clever and smart when you invent new design patterns to work around the limitations of your technology. Just writing a `clean_fork` RPC doesn't make you feel clever at all.
In any case, while I can see automatic discovery as a useful feature for web browsers (who can still punt the actual decision-making to the meat, as long as they know what the plausible next steps would be), it doesn't seem likely to me that service clients would benefit from it any more than they benefit from a thoughtfully designed and documented RPC API. Meanwhile, for whatever reason, the end-user-facing web has decided to prioritize the use case of, "you will see and interact this web page according to The Original Creative Intention Of The Author" over the use case of, "here, have some data, it links together, do whatever the hell you want with it, I don't care what fonts or UI widgets you use". REST would have been great for the second use case; it's just that nobody cares about it anymore.
One of the founding principles of REST is that links should be discoverable and resources should include the semantics of each link that's directly accessible from them.
<fork> <a rel="clean_fork" href="http://example.com/very_clean_fork" /> </fork>
And bear in mind `<a rel="clean" href="http://example.com/database/clean">` would have a very different semantic meaning from `<a rel="clean href="http://example.com/fork/clean">` or what have you.
I agree that semantic actions are a thing it'd be nice to solve and I wanted to make sure this discussion on REST touched on the fact that semantic actions are something they tried to solve. But they didn't, we've assigned common meaning to common verbs (which is pretty sweet on its own) but everything else isn't discoverable.
If you were a rather dumb client interface and got a `<a rel="clean_fork">` what would you do with that inherently except say "It isn't delete or put or patch, so I don't know what this does"
An easy way to think of it is that a Web Browser is a client for a REST architecture consisting of the web. If you create a new system and use a REST architectural style, the client app(s) will be the "browsers" for your API.
When you implement a web browser, you do need to receive sideband information about the media-type (HTML) and your client application has to be able to understand those, including what <a> and <form> mean, for example.
In a custom API, you use the same HTTP verbs if you want (REST doesn't mandate HTTP) but you need to define your media-types.
In a web service context, is there a HATEOAS web client library that I can use to make service calls without having to specify endpoints and request formats ahead of time?
> Instead of following HATEOAS guidelines, people hardcode routes...and then they also have to be versioned etc. (`api/v2/posts`).
In the web service use case, it's considerably simpler to define and specify a set number of endpoints ahead of time, define request and response formats, document that specification in OpenAPI, and use versioning if the API itself changes. This isn't RESTful. It's just RPC over HTTP. But it works and it's not "silly".
The amount of work really isn't that great when compared with having to layout routes.
Proper HATEOAS is like unit testing: people complain it takes too much work but then complain that the lack of tests is a problem.
It really isn't. There's a whole doctoral thesis describing in detail what REST is and what it is supposed to achieve.
That just means that ignorance is leading clueless developers to misrepresent a specific concept by talking about stuff they know nothing about.
Not knowing something is not the same as something not existing.
This problem is not caused by sloppy language but by militant ignorance of such a level that leads clueless people to assert that a concept has not been defined when that's patently and painfully false.
I personally like PUT even for delta updates, but a dev I was working with was obsessed with wanting PATCH.
* POST: create new object, including their primary keys. Run appropriate sanity checks.
* PUT: extract old entity object and update all attributes and dependencies, possibly deleting and regenerating all dependencies while preserving the object's keys.
* PATCH: extract old entity object and update a small subset of its attributes. Run sanity checks that are specific to this form of update, and avoid touching bits in the persistence layer that are not linked with the update.
Put is very important because total entity replacements really don't replace the role of partial updates, particularly if we consider how extensive transactions can become.
Unless, of course, I am mistaken.
PUT: create new object at a known location. object need not exist. if it does, it is replaced.
PATCH: change an object.
POST: send arbitrary data to an object. this may or may not lead to the creation of a new object at another location.
Here's a good analogy:
Graphql is docker, REST is LXC.
That's the thing about REST; you don't need any rules about what paths look like, because you shouldn't be constructing them manually. You get them from the State that was Transferred to you.
One thing that upsets me is pop psychology and second guessing of emotions (about "being upset", "excessively angry", etc) instead of arguments.
>Have fun with it.
Engineering is not about having arbitrary fun with whatever "standard" we are given.
Most of the other gripes have been responded to, but I wanted to add a comment about the "stateless" part: Its not that your Application is stateless, its the HTTP protocol itself that is. It is a contrast to other contemporary protocols like FTP or SMTP, in which you establish a connection and then perform "Commands", the order of which matters. In FTP, if you do:
CONNECT ftp.example
CD public
GET myfile.jpg
The `CD` command in Line 2 changes the behavior of the `GET` in Line 3. This different from HTTP in that each request is independent of any others. The "state" is that the FTP server has to "remember" the current working directory of each connected client. If there were need for a high-availability load-balanced FTP provider that could support tens or hundreds of thousands of simultaneous connections, it would be pretty difficult because you'd have to maintain that state across all the servers. On the other hand, the stateless nature of HTTP means we can have Proxies and Load Balancers and CDNs all over the planet, and it mostly just works.The core problem is that REST (which, recall is a description of the web architecture) requires HATEOAS. JSON doesn't naturally implement a hypertext in the way that HTML does and, further, the other end of a JSON call is almost certainly code, rather than a human, and thus isn't able to take advantage of this feature anyway.
Here are a few articles on this general idea:
http://intercoolerjs.org/2016/01/18/rescuing-rest.html
http://intercoolerjs.org/2016/05/08/hatoeas-is-for-humans.ht...
Don't assume anything, I never talked about OO, or functional programming, or event sourcing or any number of programming concepts without a "standard". Don't make up things in an attempt to further whatever point you are trying to make here. I never talked about those things and don't care about them.
Part of the challenge when people have arguments like this is that they aren't experiencing the trade-offs in the other directions they'd like to go, so it would be great to hear the concerns about an RPC alternative which restricts the HTTP verbs to GET & POST.
I mean, it's not really a progression; even inside of OO and Procedural there are a lot of differences and it's not like any of those are better than the other, they just allow you to write code that does the same thing in different ways.
nevertheless, i've had many annoying situations where i want to GET a specific list of ids, eg. /orders?ids=1235678,abcdefg and quickly run into the 2048 char limit, forcing me to design the API as a POST in all cases. combine that with additional sorting, grouping and filtering params and you're stuck.
the fact that GET is conflated with the url and has no body to pass params in is very limiting. at that point, HTTP verbs become mostly pointless.
what if you need to delete a bunch of specific records in a single HTTP request with REST? you're fucked. DELETE is designed to deal with one record at a time [1]. sure, DELETE could have a body, but the recommendation is to ignore it [2].
to operate on multiple specific records, you're stuck doing at least 2 requests. a POST that asks the server to create some temporary "collection" record. and then use the new URI of that collection to perform more operations. why do all this overhead when you can just do the delete operation with a POST request and a body filled with record ids?
i could continue, but it should be obvious that REST was designed with the server as the center of the universe. when trying to shoehorn this worldview into modern fat clients and high-perf SPAs, it very quickly falls down.
[1] https://www.restapitutorial.com/lessons/httpmethods.html#del...
[2] https://stackoverflow.com/questions/299628/is-an-entity-body...
BUT, I tend to agree. Just use GET for all requests that don't change things, and POST for those that do (important so spiders and pre-caching don't inadvertently take actions), and put everything else (including what the real verb is) in the URL or parameters.
The idea of trying to shoehorn your logic into additional PUT and DELETE verbs is unnecessary and makes it harder to use/support (e.g. HTTP forms don't support those verbs).
And... that's it. Fortunately I've never had to work with a die-hard REST evangelist, so maybe I've never had to feel the anger or frustration this post must be coming from...
...unless you've got more params than can fit into the de facto URL length limits of browsers (~2K characters for Internet Explorer), in which case you're stuck with POST.
[Edit:] > The point is that GET is not supposed to change the information stored on the server side.
The RFCs for HTTP USAGE are guidelines that are less about utility and more of an interoperability dream that was never realized. There's nothing sancrosanct about them. There have been DECADES of usage contrary (eg medical, gamedev, advertising, ERP, etc). At some point people realize it's bikeshedding issue that's more trouble than it's worth.
"Side effects" probably isn't the best term for what I meant. The point is that GET is not supposed to change the information stored on the server side.
REST is simple, simple is good. It's not perfect for everything, but it has served my purposes well for many years.
All that being said I think REST is an architectural pattern that can bring some order to the chaos. And I have seen thought experiments experiments that embrace it's constraints bring significant performance enhancements to many a system.
I think the one thing RESTish design can bring is a simplification to the communication layer, but if you're interacting with it through HTML forms then you'll need hacks to get it working in the first place (many HTTP verbs are not supported as methods by most browsers).
Basically, it's an additional tool with some value for organization, if you use it zealously you can waste years of labour building a perfectly RESTful system. Do what works for you.
https://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post
The ‘recall’ and ‘sendpromotion’ ‘actions’ are still resources: ‘the resource that does a recall’ and ‘the resource that sends a promotion.’ You don’t ‘GET’ them or ‘DELETE’ them or ‘PUT’ something in their place. You just send a request that triggers those resources to do their thing: ‘POST’. It’s not CRUD and it’s 100% valid.
Archive link https://web.archive.org/web/20181028175819/http://vmrcre.org...
In 2018 with gigs of RAM, super fast internet, and billions of Hertz, it seems like more the web should be "web scale" than it is.
I define my schema, sprinkle some directives and push it to AppSync.
Or, you could use swagger-codegen and generate your service from a handwritten OpenAPI spec.
otherwise it's pretty fine, you just need to find a good server-side framework with proper tooling (springfox for java, nest.js for node) so that you don't need to write documentation (and test-console) yourself
graphql is great if all what you want to do is to publish some data but once you need more updates or predictable performance, it's not so easy anymore, and this is not just my opinion