Yea. I assume from the article it's an alias for an HTTP interface that usually uses JSON payloads. I use those in a few projects, both work and personal. Are they Rest? Maybe. They use Django REST framework. But I think of them and describe them as HTTP APIs.
Well, if we're being truthful, none of us use REST. We're all just cherry-picking the parts of it that work for our organizations... and that's absolutely fine. The programtic discoverability portion of REST always struck me as pretty poorly thought-out anyways.
I think you missed the point. You 100% use it every day. You’re using it on this website right now. Your web browser shows you what actions you’re able to take against the HN api. Neat, huh?
The three common types of "REST" I have encountered in enterprise dev are:
1. Ancient XML/SOAP based APIs Frankenstiened to use JSON
2. Poorly implemented RPCs advertised as "JSON REST API", usually the entire thing either relies on POST requests but sometimes GET is used to make stateful changes.
3. Things that should obviously be RPC split into dozens of anemic JSON endpoints that the caller has to re-construct to get anything useful
Incidently, my company's leadership got inspired by Amazon's API culture and made # of APIs a metric that teams must hit. The result is every single endpoint being deployed as a separate API, and teams blocking access to native vendor APIs so each operation can be republished as a new API. :)
Exactly. If you ditch the bikeshedding and no true scot arguments, REST is just a loosely defined naming convention around HTTP verbs, that almost every company I have been apart of agrees on / disagrees on certain minor aspects. That being said, I am thankful that we moved to using some form of "REST" (however you define it) as it was infinitely better than WSDL/SOAP. gRPC is nice in some areas, but these days I find myself doing what the article says more often than not -- just creating business-definition specific resources that utilize GET/POST and JSON.
yawaramin, my former reasonML brother, you won't remember me, but I am so happy to have you comment on my comment even if it is tongue in cheek! Hope all is well.
If you’re designing something right now, I want to remind you of one piece of shared but uncommon wisdom:
So many of your users will not make it much past the elevator pitch for your idea. They will feel willfully or even recklessly entitled to the notion that if your tool allows something, the.n it was meant to be used that way.
I don’t have any quick fixes for that. I doubt they exist. There are some very clever things I have seen in the REST domain that are lumped under advanced topics that make a lot of sense but I don’t think I have ever seen in the wild. So if an idea feels important, you have to aim it at the journeyman if you expect it to be used at all, and beginner if you can figure out how without losing them.
In addition, I’d just like to interject for a moment. What you’re referring to as REST, is in fact, JSON/RPC, or as I’ve recently taken to calling it, REST-less. JSON is not a hypermedia unto itself, but rather a plain data format made useful by out of band information as defined by swagger documentation or similar.
Many computer users work with a canonical version of REST every day, without realizing it. Through a peculiar turn of events, the version of REST which is widely used today is often called “The Web”, and many of its users are not aware that it is basically the REST-ful architecture, defined by Roy Fielding.
There really is a REST, and these people are using it, but it is just a part of The Web they use. REST is the network architecture: hypermedia encodes the state of resources for hypermedia clients. JSON is an essential part of Single Page Applications, but useless by itself; it can only function in the context of a complete API specification. JSON is normally used in combination with SPA libraries: the whole system is basically RPC with JSON added, or JSON/RPC. All these so-called “REST-ful” APIs are really JSON/RPC.
This is fair, what I think ended up happening in the 2010s is that REST was pushed similar to XML, a solution for all application
problems (it wasn’t like Fielding was not pushing this view either), and realistically the useful scope of REST and Hypermedia is quite limited.
These so-called "REST-ful" APIs are often ad hoc RPC, underspecified in many respects, and make a twisted mess of HTTP semantics and request/response payloads; and when an edge case or shortcoming is discovered, the API sprouts more wild hairs.
What's even more "fun" is when you look through the project's history and discover that at some point, someone/s on the team fixed the problem by introducing proper JSON-RPC (per spec). Maybe they even got pretty far along with cleaning up most/all of the API. But then they moved on or got pushed aside. Other devs didn't like the JSON-RPC system ("too verbose", "too much effort to refactor/whatever") and started sprouting new "REST-ful" endpoints so they can, you know, get things done faster!
Those 2 were never the claimed benefits, and the fundamental "problem" is not a problem: a LOT of data processing is making changes to records. And you can encapsulate a lot of logic behind making changes to records.
And this makes most software easier to understand:
"Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowcharts; they'll be obvious." -- Fred Brooks
> About being able to use a RESTful API directly from a browser: browsers only use the GET and POST HTTP methods, among the ones REST associates meaning to. You cannot use a RESTful API from the browser, because the PUT, PATCH, and DELETE methods are not used by the browser, and even the POST method cannot be used without a UI. Also, even if you could, APIs are for machines, not humans. The user experience would be dreadful if you had to use a RESTful API directly from a browser, without a specific UI for it.
It's kinda true if you're thinking purely about submitting requests through `<form>` elements - but even then you can bend browsers to support other verbs.
There are multiple RFCs with lists of HTTP verbs and axios only supports the more limited set, which for my particular legacy project meant I couldn't use any of the creative ones.
That really just sounds like an axios issue - I've built in support for custom verbs with nothing but plain-old ES5 javascript. The verb is nothing more than a string component of the HTTP request and it's pretty trivial to modify it to your liking (even outside of standard verbs!).
Sure you can. You just can't specify it as a form action.
There's nothing to stop you from using form elements to get your user inputs as normal, then wiring up your own "submit" button that calls your own Javascript to use any method you want. JS fetch, for example, lets you put anything you want in the method: field. I think you can even specify custom methods that only have meaning for your specific server-side code.
They mean you can’t interact with a raw API from the browser. Unless you are just doing vanilla gets.
You might use a REST client instead or what some services do is offer a playground coded in JS to play with the end point but such a playground needs to deal with CORS.
But this also isn't true—fetch can run all the HTTP request verbs.
What they seem to mean is that you can't access most of them via the GUI directly, which is true, but their "solution" is to make queries and commands both use POST, which means they've now thrown away the ability to even access read-only endpoints via the GUI.
Ok I accept that - I guess you could F12, drop into the console and then fetch. Which is broadly similar to using curl.
I also don't like the idea of making queries and commands use POST. It kind of sucks (unless you are doing it for a website that is trying to avoid using JS for some reason).
One point this article objects to is the (ab?)use of HTTP status codes for indicating object status (i.e. 404 Your student doesn't exist). HTTP status codes are an extremely loose and flexible standard and I think that semantically most of the "RESTful" uses here are perfectly in line with expectations. Shift your thinking for a moment to consider that instead of `/user/12` linking to a script it's actually just a flat file containing some information about the user - the 404 response when the user doesn't exist is perfectly reasonable. The requestor shouldn't really care whether the request was fulfilled by apache checking file existence or some PHP script. In fact, webservers are just another kind of dynamic responder and it's important not to mystify their internal workings.
> I even used HATEOAS principles when building HTTP APIs
I found your problem.
> About being able to use any API without understanding it first
That's a HATEOAS thing, as I understand it. REST just means that you have resources and verbs, and the verbs have ~relatively~ consistent meaning. If I see some GETs and PUTs and PATCHes and DELETEs I can get a pretty good idea of what's going on. It doesn't mean I understand all the details of your application logic.
As a REST enthusiast I was excited to read this and learn a new perspective but this section
> The “benefits” REST is supposed to introduce
Is one of the more egregious straw men I’ve seen in a while. Never once in my twenty years have I heard anyone say it’s nice because “you don’t have to read the docs” or “it works in a browser”
REST helps with lots from thinking through clean data models to helping ensure consistency within an API.
The uniform interface, which is the defining characteristic of REST according to Roy Fielding[1], is what allows clients to interact with REST-ful APIs without "reading documentation":
> "A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API). From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations. The transitions may be determined (or limited by) the client’s knowledge of media types and resource communication mechanisms, both of which may be improved on-the-fly (e.g., code-on-demand). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]"
I agree with some of this - I've never found value in the different PUT/PATCH/etc verbs, and I think the lack of examples of good "pure" REST APIs indicates that pure REST doesn't work easily for most projects.
I do think this throws away some pieces that are really valuable though:
1. URLs for concepts are a good idea
2. Distinguishing between read-only operations (which can be cached) and write operations using GET and POST verbs is useful
Personally I've found myself settling on "REST-ish" JSON APIs:
- Every domain concept has a URL, and a standard consistent JSON representation that's also returned by list endpoints
- GET for read operations, POST for anything that performs a write
- I don't like content negotiation via the Accept header, so instead if I need to support alternative representations I'll do that using file extensions, .json vs .csv for example
Implicating isn't a great way to document an API. You could easily do something you didn't intend to do, which could be no big deal or extremely costly.
Yep, this is pretty much what I've settled on myself.
GET for read, POST for write. And a url made of a slash-terminated "resource" followed by an "action" verb. user 123 + edit = "/user/123/edit" ; user 123 + default(show) = "/user/123/" ; list of users = "/user/list" ; etc.
When applied to web pages, it means you can have <form action="edit"> and the "action" attribute of the form directly matches the "action" of the backend/router/API. I like that, it makes me feel warm and fuzzy. :-)
I don't like how undiscoverable it is, and how it blocks browser-based debugging. I'd much rather be able to open an issue with a GET link to a stable representation, where possible.
Cloudflare doesn't support it for caching (more specific Cloudflare doesn't obey the Vary: cache header).
It drives me crazy that every RESTful API I've ever seen in the wild has been running under a full-blown Tomcat or nginx (or some equivalent) web server when only a tiny, tiny subset of the HTTP protocol is actually needed for the API being supported.
I went into this article strongly disagreeing but I think the alternative presented at the end are valid ways to structure an API and for those who very loosely follow REST structuring would probably consider the alternatives "REST" too.
REST seems to have different definitions depending who you talk to. Some define it very strictly (as the opening of the article seems to do) and others define it very loosely (as a JSON interface with GET/POST/etc commands). For those who implement REST loosely, the suggested alternatives fit right in.
Now I'm not a web dev, I've played around way back in the CGI era and since then moved on to other things. But my impression was that part of the point of REST was making it fit in a bit better in how the protocol is supposed to behave.
Early on there was a lot of stuff that did nothing but GET for everything. Done that way any layer in the middle can't make any sensible caching decisions, and even the logs are annoying to look at when you can't quickly tell apart what's retrieving data and what's changing it.
So my impression was that part of the point of REST is to shoehorn an API into something that makes sense in the way HTTP is supposed to work, and you're less likely to have something go dramatically go wrong because some cheap ISP is running a transparent proxy and deciding that the GET that's supposed to save something doesn't actually need to happen, because look, this user already made a GET to the same URL 5 seconds ago.
Now of course today everything uses SSL, but early on it wasn't that weird to run into some awful ISP that would do some sort of aggressive caching to save on upstream bandwidth, if not to actually try to recompress stuff in flight.
The trading example is bad, since we do talk about posting limit orders even outside of a REST context -- though it refers to it staying in the book and not matching immediately.
Just to clarify, my incredibly vague point is that people having been saying FreeBSD and now REST are or should be dead for so long but they never die :)
The article is good, and I get the point. However, from experience, this:
> POST on /queries/enlisted-students-on-joining-date/version/1 { "date": "2023-09-22" } to retrieve all students that joined on a given date.
always ends up in a complete and absolute mess, where every possible query gets it's own random name, different parameters, ending up with duplicates all over the place. Also, while it can be possible to cache these POST requests (responses), it's additional work and more friction compared to REST. I'm not convinced the tradeoff is worth it in this particular case.
All in all, I don't know if the current proposal can be an alternative either but the idea of a "REST-lite" goes in the right direction and it's a great start.
However this is a complete no for me:
> When a requested student is nonexistent, your API can return 200 OK HTTP status code with a { "user": null, "message": "No user exists with the specified ID" } response body.
this is the standard we have company-wide and it works pretty well, unless you make a mistake in the uri (like picking up the wrong api version). however, all apis will return some info on their root, so it's easy to distinguish and troubleshoot
404 means that there is no resource at the requested URI. But in the case you're discussing, there is a resource at the requested URI; it's just a resource that says there's no user there, instead of a resource that gives data for a user.
In other words, using 404 the way you describe conflates two different things: an invalid user URI (maybe the range of possible user IDs is restricted, or you typed in the URI wrong) and a valid user URI that just doesn't have a user there at the time you made your request. But you probably don't want those two things to be conflated; you want them to be distinguished. That's the article's point.
I thought a practical benefit of REST (probably the only one I really care about) is that it makes APIs more scalable by allowing caching proxies to safely cache responses to GET requests? At least I thought that was a big part of the original pitch, but I don't see it mentioned here.
REST is a design pattern. Do you use the bridge pattern for all your Java code? Nah! Do you use an ORM for all your data access and never drop down to SQL? Nah.
83 comments
[ 4.0 ms ] story [ 151 ms ] threadAre you offering an alternative or inviting gratitude by pointing out that things could be much worse?
1. Ancient XML/SOAP based APIs Frankenstiened to use JSON
2. Poorly implemented RPCs advertised as "JSON REST API", usually the entire thing either relies on POST requests but sometimes GET is used to make stateful changes.
3. Things that should obviously be RPC split into dozens of anemic JSON endpoints that the caller has to re-construct to get anything useful
Incidently, my company's leadership got inspired by Amazon's API culture and made # of APIs a metric that teams must hit. The result is every single endpoint being deployed as a separate API, and teams blocking access to native vendor APIs so each operation can be republished as a new API. :)
I think that ship has sailed. REST in practice just means following HTTP semantics.
To be honest, I was pulling your leg but I mostly do the same thing you're doing when dealing with APIs at work :-P
If that were true, it would be awesome. Because full HTTP semanics are quite intricate, and cover a lot
- HTTP decision diagram: https://github.com/for-GET/http-decision-diagram (full docs: https://github.com/for-GET/http-decision-diagram/blob/master..., just the PNG: https://camo.githubusercontent.com/c26df6d372790e9f24d7e16d2...)
- Know your HTTP well: https://github.com/for-GET/know-your-http-well
So many of your users will not make it much past the elevator pitch for your idea. They will feel willfully or even recklessly entitled to the notion that if your tool allows something, the.n it was meant to be used that way.
I don’t have any quick fixes for that. I doubt they exist. There are some very clever things I have seen in the REST domain that are lumped under advanced topics that make a lot of sense but I don’t think I have ever seen in the wild. So if an idea feels important, you have to aim it at the journeyman if you expect it to be used at all, and beginner if you can figure out how without losing them.
I'd like to just leave a few links on REST here for the reader's consideration:
https://htmx.org/essays/how-did-rest-come-to-mean-the-opposi...
https://intercoolerjs.org/2016/01/18/rescuing-rest.html
https://htmx.org/essays/two-approaches-to-decoupling/
https://htmx.org/essays/hypermedia-apis-vs-data-apis/
https://htmx.org/essays/hypermedia-clients/
https://intercoolerjs.org/2016/05/08/hatoeas-is-for-humans.h...
https://htmx.org/essays/hateoas/
In addition, I’d just like to interject for a moment. What you’re referring to as REST, is in fact, JSON/RPC, or as I’ve recently taken to calling it, REST-less. JSON is not a hypermedia unto itself, but rather a plain data format made useful by out of band information as defined by swagger documentation or similar.
Many computer users work with a canonical version of REST every day, without realizing it. Through a peculiar turn of events, the version of REST which is widely used today is often called “The Web”, and many of its users are not aware that it is basically the REST-ful architecture, defined by Roy Fielding.
There really is a REST, and these people are using it, but it is just a part of The Web they use. REST is the network architecture: hypermedia encodes the state of resources for hypermedia clients. JSON is an essential part of Single Page Applications, but useless by itself; it can only function in the context of a complete API specification. JSON is normally used in combination with SPA libraries: the whole system is basically RPC with JSON added, or JSON/RPC. All these so-called “REST-ful” APIs are really JSON/RPC.
The situation is even worse than that because JSON-RPC is well specified:
https://www.jsonrpc.org/specification
These so-called "REST-ful" APIs are often ad hoc RPC, underspecified in many respects, and make a twisted mess of HTTP semantics and request/response payloads; and when an edge case or shortcoming is discovered, the API sprouts more wild hairs.
What's even more "fun" is when you look through the project's history and discover that at some point, someone/s on the team fixed the problem by introducing proper JSON-RPC (per spec). Maybe they even got pretty far along with cleaning up most/all of the API. But then they moved on or got pushed aside. Other devs didn't like the JSON-RPC system ("too verbose", "too much effort to refactor/whatever") and started sprouting new "REST-ful" endpoints so they can, you know, get things done faster!
And this makes most software easier to understand:
"Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowcharts; they'll be obvious." -- Fred Brooks
https://faithlife.codes/blog/2023/09/rest-level-zero-dot-fiv...
[1]: https://github.com/twitchtv/twirp
This.. isn't true?
None of my browsers seem to have PUT, PATCH, and DELETE baked into the standard UI (or even POST really), so maybe it is true?
There's nothing to stop you from using form elements to get your user inputs as normal, then wiring up your own "submit" button that calls your own Javascript to use any method you want. JS fetch, for example, lets you put anything you want in the method: field. I think you can even specify custom methods that only have meaning for your specific server-side code.
You might use a REST client instead or what some services do is offer a playground coded in JS to play with the end point but such a playground needs to deal with CORS.
What they seem to mean is that you can't access most of them via the GUI directly, which is true, but their "solution" is to make queries and commands both use POST, which means they've now thrown away the ability to even access read-only endpoints via the GUI.
Yep, or even custom ones that you've defined for specialized purposes (obviously you have to make sure your server also understands them).
I also don't like the idea of making queries and commands use POST. It kind of sucks (unless you are doing it for a website that is trying to avoid using JS for some reason).
I found your problem.
> About being able to use any API without understanding it first
That's a HATEOAS thing, as I understand it. REST just means that you have resources and verbs, and the verbs have ~relatively~ consistent meaning. If I see some GETs and PUTs and PATCHes and DELETEs I can get a pretty good idea of what's going on. It doesn't mean I understand all the details of your application logic.
> The “benefits” REST is supposed to introduce
Is one of the more egregious straw men I’ve seen in a while. Never once in my twenty years have I heard anyone say it’s nice because “you don’t have to read the docs” or “it works in a browser”
REST helps with lots from thinking through clean data models to helping ensure consistency within an API.
I've seen multiple people argue these points. shrug
> "A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API). From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations. The transitions may be determined (or limited by) the client’s knowledge of media types and resource communication mechanisms, both of which may be improved on-the-fly (e.g., code-on-demand). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]"
- https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...
The missing piece here is hypermedia, which is a requirement for a REST-ful API, as Fielding notes again with frustration in the same essay.
[1] - https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_st...
I do think this throws away some pieces that are really valuable though:
1. URLs for concepts are a good idea
2. Distinguishing between read-only operations (which can be cached) and write operations using GET and POST verbs is useful
Personally I've found myself settling on "REST-ish" JSON APIs:
- Every domain concept has a URL, and a standard consistent JSON representation that's also returned by list endpoints
- GET for read operations, POST for anything that performs a write
- I don't like content negotiation via the Accept header, so instead if I need to support alternative representations I'll do that using file extensions, .json vs .csv for example
2. The method to use is implied by the relationship of a link.
GET for read, POST for write. And a url made of a slash-terminated "resource" followed by an "action" verb. user 123 + edit = "/user/123/edit" ; user 123 + default(show) = "/user/123/" ; list of users = "/user/list" ; etc.
When applied to web pages, it means you can have <form action="edit"> and the "action" attribute of the form directly matches the "action" of the backend/router/API. I like that, it makes me feel warm and fuzzy. :-)
I find one good use case for them when a browser can make good use case with a SSE whilst another client just needs a regular _json_ response
Cloudflare doesn't support it for caching (more specific Cloudflare doesn't obey the Vary: cache header).
The real mistake is graphql. Like microservices, so many companies get hamstrung with this. I’ve said my piece.
REST seems to have different definitions depending who you talk to. Some define it very strictly (as the opening of the article seems to do) and others define it very loosely (as a JSON interface with GET/POST/etc commands). For those who implement REST loosely, the suggested alternatives fit right in.
Now I'm not a web dev, I've played around way back in the CGI era and since then moved on to other things. But my impression was that part of the point of REST was making it fit in a bit better in how the protocol is supposed to behave.
Early on there was a lot of stuff that did nothing but GET for everything. Done that way any layer in the middle can't make any sensible caching decisions, and even the logs are annoying to look at when you can't quickly tell apart what's retrieving data and what's changing it.
So my impression was that part of the point of REST is to shoehorn an API into something that makes sense in the way HTTP is supposed to work, and you're less likely to have something go dramatically go wrong because some cheap ISP is running a transparent proxy and deciding that the GET that's supposed to save something doesn't actually need to happen, because look, this user already made a GET to the same URL 5 seconds ago.
Now of course today everything uses SSL, but early on it wasn't that weird to run into some awful ISP that would do some sort of aggressive caching to save on upstream bandwidth, if not to actually try to recompress stuff in flight.
But in short, articles arguing thst the most popular api format needs to be put to rest can't be anything else but highly opinionated clickbait
> POST on /queries/enlisted-students-on-joining-date/version/1 { "date": "2023-09-22" } to retrieve all students that joined on a given date.
always ends up in a complete and absolute mess, where every possible query gets it's own random name, different parameters, ending up with duplicates all over the place. Also, while it can be possible to cache these POST requests (responses), it's additional work and more friction compared to REST. I'm not convinced the tradeoff is worth it in this particular case.
All in all, I don't know if the current proposal can be an alternative either but the idea of a "REST-lite" goes in the right direction and it's a great start.
However this is a complete no for me:
> When a requested student is nonexistent, your API can return 200 OK HTTP status code with a { "user": null, "message": "No user exists with the specified ID" } response body.
If nothing is found, I want a 404! :D
- 404 if resource requested by id
- 200 with empty list of results if it was a 'search' type request with params (not referring directly to an id)
In other words, using 404 the way you describe conflates two different things: an invalid user URI (maybe the range of possible user IDs is restricted, or you typed in the URI wrong) and a valid user URI that just doesn't have a user there at the time you made your request. But you probably don't want those two things to be conflated; you want them to be distinguished. That's the article's point.