I'm going to have to call bullshit on that one. REST is one of the more successful strategies we've come up with for connecting systems, this is just another case of letting perfect stand in the way of good enough. Using GET for non-destructive operations and POST for updates and deletes is a nice, portable compromise. I've been trying hard for years to find a reason to bother with PUT, but so far I've found it not worth the effort.
It is considered best practice to separate out POST and PUT by PUT being idempotent while POST is not: https://stackoverflow.com/questions/18485621/what-is-meant-b.... This allows you to reason better about API calls in code by their HTTP method without having to check the fields sent.
> I've been trying hard for years to find a reason to bother with PUT, but so far I've found it not worth the effort.
And right there, at your final sentence, you basically described why REST has more or less failed.
GET and POST are useless for implementing a complete application protocol. You'd basically overload these http verbs to the point where you would implement your own protocol. And that's what most people do anyway. You choose to not use PUT, some other person chooses to not use PATCH or HEAD and I choose to curse vehemently every time I have to use someone's service.
REST is nothing but loosely connected guidelines that nobody uses in the same manner.
Maybe it is fair to call REST a failure in that it is flawed, and there aren't perfect implementations. But I just had to go through a SOAP XML integration, and it was ten times more painful than the worst REST experience I've had. So I still see REST as one of the biggest tech wins in a long time.
Really? I made one yesterday based on a WSDL from a customer. The whole API was auto generated in type safe Scala in seconds. After adding authentication configuration and some sensible timeouts, I had the whole thing running in two hours. The SOAPui auto generated a mock test and load tests with which I could mimic specific weird responses.
The REST API I had to forward through however had no good documentation, no client library, so I was forced to write json serializers and reverse engineer the code. Overall, when you have a well written SOAP interface (rare, admitted), development time can be greatly reduced.
In order to get the well written SOAP interface, it helps to have the right tools and be used to using them. I think that increases the barrier to entry on using SOAP, which leads to the idea that SOAP is terrible and crufty compared to REST.
I learned SOAP relatively recently, but well after it was a fad. Today, my experience would be like yours if I had to make a SOAP service with just a WSDL. But when I started out? It would take a longer for me to wrap my head around all of it. I can't imagine how confusing it would be if I had to do it all without the benefit of working on a team whose focus is a SOAP-based product. I dunno if I would know where to begin.
Compare that to REST. Even if you know next-to-nothing to start, you can do a basic REST tutorial for just about any stack in an hour, and get a basic implementation of an API up in an afternoon.
Did you really just complain that REST is bad because you couldn't find an auto-generation tool to do your work for you? Because that's hilarious.
Also, you don't seem to have looked terribly hard, because there are a few really powerful tools out there for autogenerating server and client code for REST APIs, as well as mock servers and a whole host of other tooling (See: Swagger, RAML, API Blueprint for starting points).
I wonder how you arrive at your conclusions. It's rather hilarious, to be honest. I've found that good machine readable specifications of rest interfaces are as rare as well designed SOAP interfaces.
I've used a variety of tools to generate and test REST interfaces in the last ten years. To a mixed success, I must say.
REST has "failed" in the same way that many original visions of the web/APIs/protocols have "failed" - you have a few "no-true-Scotsman" purists complaining about differences in implementation; meanwhile a great many real-world developers are quite happy and productive in a REST-like paradigm and don't particularly care that their API doesn't fit some Platonic ideal.
Could things be better? No doubt. But REST (or something like it) is largely "the way things are built" these days and most people don't mind. Calling it a failure is quite a stretch IMO.
I'm not claiming that REST is a protocol. I'm saying that the de facto state of the REST paradigm today is analogous to some protocols which have been twisted to support use-cases far beyond what their designers intended, in ways that make purists squeamish, but make developers happy that their shit works.
> use-cases far beyond what their designers intended
OK, I get what you're saying. Problem is that as far as I can see REST is perfect for S3-like services, Maps(?) and slightly more than basic CRUD applications.
You are bound to discover its limits very soon. The gazillions of books and blogposts out there heralding it as a serious interface are not helping either.
BTW, I don't know about other people criticizing, I am definitely not a purist. But after ~10 years of dealing with REST in various capacities(startups to Enterprises), I am a bit tired and can't wait for something to replace it.
> As the article points out, there are all too many HTTP libraries that only support GET and POST, not the more "esoteric" verbs like PUT and DELETE.
GET and POST are all you need: "Return representation of available operations" and "apply this operation". It's the lambda calculus applied to the web (see Waterken's web-calculus for a more formal treatment).
You might say that this is too anemic a foundation and you want more built into the protocol level to handle some common tasks, but I'm not convinced it's necessary or even desirable. At some point requirements will change and some of those tasks will be supplanted, but we'll have to live with them forever if we bake it into the protocol.
You're just supporting my argument and weakening REST's case.
I can do you one better. If you managed to reduce everything down to GET and POST here's an idea; just use POST for everything. Boom. You just re-invented SOAP.
> You're just supporting my argument and weakening REST's case.
How? Perhaps you should actually elaborate your argument. REST doesn't depend on the use of verbs, it's an architecture that elaborates the requirements for object designation (URLs), object lifetimes (statelessness) and hypermedia-driven service discovery (HATEOAS). Only GET and POST in HTTP are required to fulfill these requirements. If there's actually something wrong with that, then lay it out.
> If you managed to reduce everything down to GET and POST here's an idea; just use POST for everything. Boom. You just re-invented SOAP
Except you can't in a world with side-effects. You could do exactly what you say if every POST were guaranteed to be idempotent. Every request could carry a full payload like a POST request and a unique identifier to ensure at-most-once semantics. That would be a fine protocol, and totally REST compatible. What's the problem exactly?
Finally, SOAP carries far more baggage than you imply. It's a false equivalency.
It's not a false equivalency. Books have been written about it and describe how you defeat REST by doing what you describe.
When you encapsulate most of your operations under POST you basically create your arbitrary protocol. No assumptions can be made about your service. You can make your own assumptions about your own service, but the others can't.
> That would be a fine protocol, and totally REST compatible. What's the problem exactly?
The problem would be that it wouldn't be REST compatible. You should clearly read a few books on the subject. Friendly advice, not a snarky comment.
REST already has idempotent mutating operations, like PUT and DELETE. It's not just GET that's idempotent. So clearly the problem is that you redefine your own protocol, with your own semantics, even though we already have plenty of standardized methods/response codes.
> If there's actually something wrong with that, then lay it out.
You have obviously missed a ton of bibliography on the subject. Before reading random blog posts from random people who have their arbitrary assumptions about what REST is, I'd suggest reading a few books on the subject.
Honestly sorry if I sound snarky, but after 10 years on working with such APIs, and after reading countless books on the subject, it never ceases to amaze me how people still think that GET and POST are enough. But I don't blame you, but the browsers who basically broke the protocol by just using those 2.
> When you encapsulate most of your operations under POST you basically create your arbitrary protocol. No assumptions can be made about your service.
And you shouldn't make such assumptions, you should just use the input parameters exposed in hypermedia which you obtained from a public service entry point. It's called encapsulation and that's REST. Again, what's the problem? All I hear is complaining that REST doesn't work the way other architectures work. Big surprise.
Certainly REST's HATEOAS can sometimes make a service less efficient as compared to some alternatives (so it can preserve encapsulation and support upgrade), but that's not the claim you're making. You're claiming some kind of insufficiency.
> The problem would be that it wouldn't be REST compatible. You should clearly read a few books on the subject. Friendly advice, not a snarky comment.
I've read Fielding's thesis, thanks. I understand REST perfectly well.
> REST already has idempotent mutating operations, like PUT and DELETE. It's not just GET that's idempotent.
So what? PUT and DELETE don't have the necessary semantics. GET representation, apply operation listed in representation via POST. What more do you need?
> Honestly sorry if I sound snarky, but after 10 years on working with such APIs, and after reading countless books on the subject, it never ceases to amaze me how people still think that GET and POST are enough
You still haven't pointed out a single reason why GET+POST are not enough or how they "break REST". I'm not asking for "a ton of bibliography", I'm asking for a single example. An existence proof that my claim is false. It should be trivial if this shit ton of bibliography exists.
Frankly, most of this vaunted "bibliography" since Fielding's thesis has been non-REST crap. It's amazing how easily people can misunderstand a 150 page thesis.
Exactly. The whole "RESTful APIs" thing never was - I've been saying this since I first heard the term used. It's not a standard, just HTTP APIs, implemented wildly.
Nothing wrong with that, but don't call it a standard and don't try to name it something it isn't.
> "REST is nothing but loosely connected guidelines that nobody uses in the same manner"
But is that really a huge problem?
Look at more rigorous rpc standards with more rigorous standards and formal interface definitions: RMI, xmlrpc, CORBA, SOAP, Thrift, AMF... I'm sure there are loads and loads of real world systems using these and they have their place, but REST has succeeded in a large niche that they have not.
That's really the winning point of REST: it's just formal enough to put most people on the same page, and loose enough to adapt to different requirements without too much effort.
It's useful to remember that REST was borne and adopted mostly in reaction to SOAP and XMLRPC (which in turn were basically replacing CORBA and RMI to work around the firewall). XMLRPC was too loose, and SOAP was too formal (way too formal). REST hit the sweet spot.
However, it's sad that the result was often that people just retooled their crappy SOAP / RPC systems to use decent URLs and called it REST. My litmus test is usually "returning 200 OK on all calls" - if you're doing that, that's not REST. Use proper HTTP return codes and put additional error messages in the payload, it's not hard. Also, if you have a job queue, give each job a URL with the ID and GET that to retrieve status.
Rest is a well defined semantic everybody bastardized because they find shameful to say they use json-rpc on the resume or elsewhere. There's a difference there.
>REST is nothing but loosely connected guidelines that nobody uses in the same manner.
I don't see a problem with this. In fact, I'd love it if everyone accepted this instead of whining that something isn't truly "RESTful."
For instance, the app I'm working on deliberately does not implement HATEOAS. I appreciate the academic effort behind REST and RESTfulness, but ultimately I view it only as an ideal to tend toward. As you said, it's a guideline.
What you just described is only the bare shell of REST. It would also apply to many types of API that don't follow REST principles. One thing this article gets right is that nobody is really RESTful because nobody knows what it means.
There's usually a dollop of RPC in most APIs - and there's nothing wrong with that - but the 'pure vision' of REST is similar to the 'pure vision' of the Semantic Web. It's a dream for the next life not something we will receive in this one.
I'm fine with using ideas that make sense and rejecting the ones that don't. It's still solid advice for API design, and the most successful approach we've come up with. Doing REST to the letter always turns into some kind of modern art installation with lots of hammers looking for nails; this is the technology department, religion is down the corridor. I have full confidence that the authors considered these ideas, not laws.
So… why do you call it REST rather than just HTTP since that's exactly what it is? You're using GET and POST for what they were built for, great, that's just HTTP, why not call it that?
> I have full confidence that the authors considered these ideas, not laws.
That's like saying the authors of the word "bicycle" considered it being two wheeled idea, not law, and you'll call your 8-wheeled ATV a bicycle because it has wheels and you think wheels are nice and solve your problem and the religion department is down the corridor.
Yeah wheels are nice and solve your problem, your motorised monstrosity is not a bicycle though.
I'm leaning more and more in the direction of ditching the term "REST API" and just saying our APIs are Web or HTTP APIs. I'm beginning to think people just say REST API because it looks better on their CV, not because its helpful to other developers who may end up using it.
I've made this argument in a much better form elsewhere but I don't have much time.
To my mind the benefit of REST purism was that it killed SOAP. A similar thing has happened at other stages of tech development (e.g. CSS purism cured us of all those awful <table> excesses).
The purism was a mistake and the details were wrong but it was necessary to get everyone behind a common goal - getting rid of something worse.
You don't need PUT nor DELETE. It is OK to use POST[1].
Most people don't understand REST. It is not a standard, it is not a set of practices. It is an architectural style and the web is built on it.
You can choose to follow the style (which is so much more than naming methods and URIs) or fight it. The dissertation is pretty clear about it[2], but most people ignore it because there are no code samples.
Ignoring the dissertation is OK. It was designed for people to understand how the web was designed, not as an implementation guide.
Ignoring REST is impossible, the web is built on it.
- The uniform interface is in every URI (if you use them, you use REST).
- The code-on-demand constraint is everywhere (if you use JavaScript, you're using REST).
- Hypermedia is everywhere (if you have links on your web page, you're using REST).
- The client-server constraint I don't even have to bother explaining (although WebRTC might bring P2P back in the game).
- The layering is everywhere (if you do haproxy, varnish, squid or similar, your using REST).
The _RESTful API_ thing is just a myth. People needed a name to discourage tunneling RPCs over HTTP, so they invented these loosely defined terms to push the idea. It should be called HTTPful, because it tells more about avoiding re-implementing HTTP features than it tells about the REST style.
Although PUT is not necessary using it for idempotent calls like it was designed to do actually helps developers using the API understand the intent of the call better. They don't have to worry about undesired consequences/side effects. Which I think is a useful pattern.
I agree that it's potentially useful, but it also adds it's share of complexity to any implementation I've come across. And most proposed uses I've seen do not obviously benefit from the idempotent approach, from my experience it often complicates the server implementation. I've found using the REST approach for URLs, separating reads from writes and using status codes a good compromise.
> Although PUT is not necessary using it for idempotent calls like it was designed to do actually helps developers using the API understand the intent of the call better. They don't have to worry about undesired consequences/side effects.
This can also be solved by futures. Any POST that you'd like to retry, which will be any of them given the unpredictability of network partitions, can be bound to a future so the operation is applied only once and all future attempts simply return the bound value.
The point of having something like PUT (that is known to be imdepotent) is that it can be retried by any of the layers in the stack, instead of having a full roundtrip back to the client on every retry.
And it's not always safe to retry POSTs. If POST is an insert, for example, retrying it would produce two inserts. And this can have interesting consequences when processing responses. Suppose that you have sent a POST request, but before you could read the response, connection dropped. You didn't get a chance to read the status code, so you don't know if your insert succeeded or not. If it didn't, you want to retry - but you'll need to do a GET first to check the current state of affairs. OTOH, if you're doing a PUT, you can just retry immediately without re-checking.
> And it's not always safe to retry POSTs. If POST is an insert, for example, retrying it would produce two inserts. [...] Suppose that you have sent a POST request, but before you could read the response, connection dropped.
My previous post already covered idempotent POSTs via futures. The fact is, only the application can decide whether a POST is safe to retry arbitrarily or must be made safe by binding to a future. The PUT is merely a small optimization that is now obviated by the spread of HTTPS.
If I understand your point correctly, you're saying that when something is talking over HTTPS, the middleware doesn't get to see the verbs, and so it can't optimize for them anyway. But if part of your connection is using different transports, then middleware in those segments can observe the verbs and react accordingly (including e.g. local retries in face of adverse network conditions, to avoid expensive end-to-end roundtrips).
While technically correct, I'm not sure how this is useful. You use HTTPS to communicate with an endpoint you trust, and anything beyond that is internal network infrastructure which is much more reliable than the HTTPS hops. The utility of local retries on this last hop don't seem compelling.
> The PUT is merely a small optimization that is now obviated by the spread of HTTPS.
Idempotence can be useful knowledge for client-side caches, so HTTPS doesn't obviate the value of the PUT (or, for the same reason, DELETE) vs. POST distinction.
And yet you don't provide a single concrete reason. And even go on to say the non-REST way you use REST at your team.
>REST is one of the more successful strategies we've come up with for connecting systems, this is just another case of letting perfect stand in the way of good enough. Using GET for non-destructive operations and POST for updates and deletes is a nice, portable compromise. I've been trying hard for years to find a reason to bother with PUT, but so far I've found it not worth the effort.
Note how none of this (or even few parts of what the author of TFA described) is actually REST as defined by Roy.
Taking ideas from REST and putting it into your JSON-RPC API doesn't make your API REST. But you call it REST anyways.
It's like reading a book on building a house and using ideas to build a shed. Sure your shed has electricity and a sink but it's still a shed, not a house.
Same with terms like RESTful. You don't call your shed a "house like building" as it's missing key pieces of a house.
REST requires HATEOAS. The only real implementation is the world wide web. Everything else is really JSON-RPC or some other protocol with a few ideas borrowed from REST.
Http-rpc is. People call it rest nowadays even when it isn't nor understand the state tranfer part of rest. Not saying it's your case specifically but I'we seen exactly zero http-rpc API implementing rest but a shitton people claiming their json-rpc interface was.
PUT is for the case where the client knows the location of the resource to be created, whereas POST is for the case where all that is known is the location of a logical parent resource.
The "true spirit" of REST, to me, is that there's a certain set of things you can do when creating an API that will let you re-use the huge amount of HTTP middleware that's been written and get correct (and useful!) semantics from it. Caches (browser-, edge-, and server-side-), load balancers, forward- and reverse-proxies, application-layer firewalls, etc. will all "just work" for your software if you do REST correctly, and won't have any weird edge-cases.
Re-implementing those same semantics in your own messaging protocol / format, without intertwining the concerns of the protocol and the message format, throws away any/all of those benefits. You need a protocol that guarantees that middleware can "look inside" the messages it's passing (or at least their metadata), in order for any of this to work. That's why HTTP has both a transparent part (req path+headers; resp status code) and an opaque part (req and resp bodies) to each message: the transparent part is there for data that affects middleware behavior, while the opaque part is there for data that doesn't.
Note that that doesn't mean you're stuck with HTTP1. SPDY/HTTP2 is effectively an entirely different protocol—but it keeps the same semantics of requiring certain properties of the metadata tagged onto each message at the protocol level, so that anything that speaks the protocol can use that metadata to inform its decisions.
The "true spirit" of REST, to me, is that there's a certain set of things
you can do when creating an API that will let you re-use the huge amount of
HTTP middleware that's been written and get correct (and useful!) semantics
from it. Caches (browser-, edge-, and server-side-), load balancers,
forward- and reverse-proxies, application-layer firewalls, etc. will all
"just work" for your software if you do REST correctly, and won't have any
weird edge-cases.
Doesn't that assume that the middleware also implements REST correctly? As the article points out, there are all too many HTTP libraries that only support GET and POST, not the more "esoteric" verbs like PUT and DELETE.
The article says "most client and server applications don’t support all verbs or response codes" which, in my experience, is not true. There are some but it's definitely not "most". For one, if you're writing both sides, don't build on client or server software that sucks. Sure, HTML forms don't support PUT and DELETE but how often to you use HTML forms instead of ajax requests (which do support those methods)? And, if you subscribe to a little bit of CQRS and Event Sourcing ideas, PUT and DELETE don't really make sense since you should really be POSTing commands to do those things. Where they do make sense is when manipulating files directly which I don't think comes up much these days.
What we really need is a set of verbs that allow to reliably distinguish between these three types of operations:
1. Pure read.
2. Impure (stateful) read.
3. Idempotent write.
4. Any other write.
There's no particular reason to separate inserts, updates, deletes etc as part of the protocol - they're all just different kinds of writes, and middleware doesn't derive any benefit from being able to distinguish them. Thus, this can be a part of the payload.
On the other hand, the difference between reads and writes, and the two subdivisions within each, do matter for purposes such as caching and automated error recovery (e.g. a proxy can repeat an idempotent write a few times before returning the error to the originator of the request).
In REST, we have GET for #1 and #2, PUT and DELETE for #3, and POST for #4. In practice, this is often simplified to just POST used for both #3 and #4, but that loses a valuable distinction (but is unfortunately often necessary because of the lack of support for other methods). On the other hand, the PUT/DELETE distinction is largely pointless.
Indeed, I forgot some. Then again, last time I tried to use PATCH, I found that support for it in various places in the stack was patchy enough to make it a non-starter.
It's not worth making the distinction between idempotent and non-idempotent writes given the possibility of network partitions. Every write must be made idempotent because all you can do is retry in this case. PUT is merely an optimization on idempotent POST requests, one that will become progressively rarer as HTTPS continues to spread.
POST requests can be made idempotent by binding the result of processing that request to a future, so every subsequent request simply returns the already computed result.
Impure reads are the default, and pure reads are designated by long-lived cache headers, ie. it's an impure read that lasts as long as the server responds.
So really you just need GET and POST, and server-side frameworks should make POST requests idempotent by embedding some notion of futures for side-effecting operations. See the Waterken server for the first development platform to really get this right.
It can be as long as you have some kind of identity information associated with the request, and provided alongside any requests that are the 'same'.
e.g. Instead of saying "Insert a transaction for £20", you say, "Insert a transaction that entity A calls 1234, for £20".
Stripe use something like this to ensure that as long as you call their API to ask for a payment and use the same key, they won't charge the person twice.
Requesting an insert can be idempotent. Each non-idempotent operation is tagged with a unique identifier, if the server doesn't have inserted data tagged under that identifier, then it performs the insert, if it does, then it returns the usual success code as if it had just performed the insert. This unique identifier is simply a durable representation of a future which I described above.
This would seem to require the identifiers to be attached to records in perpetuity (i.e. it would basically require client-generated IDs everywhere), so that the server can reliably verify that this operation has already produced a record. I can see it working, but it's a far-reaching change, that may not be easy to adopt for existing data storage schemas.
> This would seem to require the identifiers to be attached to records in perpetuity (i.e. it would basically require client-generated IDs everywhere)
Not sure what you mean by client-generated. The server-side app generates the id because it has to store and interpret it. This can be as simple as a sequence number, similar to how TCP guarantees delivery. It depends on the schema really.
This is the simplest way to ensure you can perform arbitrary retries of POST in case of a network partition.
This data doesn't even need to be integrated with your app's schema, although that's ideal so you can manage the storage lifetime. But you could use an entirely separate store for GUIDs and cached replies, and so it becomes transparent to your app and just becomes another layer.
> Not sure what you mean by client-generated. The server-side app generates the id because it has to store and interpret it.
Per the description above:
"Each non-idempotent operation is tagged with a unique identifier"
Since the operation originates on the client, the client has to tag it with the identifier, no? And the server has to store this identifier in a way that associates it with any data affected by that operation in a non-idempotent way.
Or are you saying that the client first has to make a round-trip to the server to generate the ID, and then use that server-provided ID for the actual POST?
> Or are you saying that the client first has to make a round-trip to the server to generate the ID, and then use that server-provided ID for the actual POST?
This is always the case for REST given HATEOAS, ie. you've already made some hypermedia requests to obtain the URL of the endpoint to which you will POST.
Unless the resource you're posting to actually is the public entry point of your service, but that would be very unusual.
Wait, but what about the request used to obtain the URL of endpoint to which you're posting? Isn't that one then not idempotent (since it would create new URLs every time)?
Generally speaking, what is the flow like? Suppose I allocated myself an endpoint, but then never posted anything to it - what does the endpoint actually contain then, if queried? Do unused ones get "garbage collected" somehow eventually?
> Wait, but what about the request used to obtain the URL of endpoint to which you're posting? Isn't that one then not idempotent (since it would create new URLs every time)?
Not necessarily. The numbers don't have to be stored before they're actually used by clients. For instance, you could return a simple integer, like an object version #, and an HMAC(integer, resource URL) to ensure the client can't tamper with it. You only store data under that integer when the user successfully POSTs to that resource for the first time.
> Generally speaking, what is the flow like? Suppose I allocated myself an endpoint, but then never posted anything to it - what does the endpoint actually contain then, if queried?
There are many possible designs here. I prefer something like this in CRUD-like contexts [1], because it gets me a fully auditable change history, optimistic concurrency control and all the storage needed is fully integrated into the app schema in a sensible way.
Combined with the HMAC described above, you don't need to preemptively allocate any storage for idempotent POSTS and you can use simple integers as your unique identifiers. So a POST against a version number that's not the latest version would simply return the version that followed if their POST was the one that succeeded, or a redirect to the latest version if someone else had updated it.
Hopefully you can imagine various relaxations on this to make other trade offs. For instance, a much simpler approach would be to return GUIDs for each possible POST, and you just store each GUID associated with the object when a POST succeeds. If the object's current GUID is the GUID the user is posting, return the current data with 200 OK, otherwise return a 301 Moved to a URL referencing the latest version and let the client try to apply their updates to that. The storage can be reclaimed after a suitable period of time; say a month if your app is for browser clients
Because applications have state. In fact, the vast majority of reads in any applications are stateful (the database backing your app is also state, you know; I'm not talking just about session state here).
By "pure" here I mean that we're talking about a pure function of its inputs.
Look into WebDAV and you'll find plenty :) LOCK, UNLOCK, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH. And also REPORT, SEARCH, and various version-control operations.
Oh sure, but the context is REST apis, not WebDAV :)
PATCH allows two users to update different fields on the same resource at the same time with no conflicts. Otherwise, they'd use PUT and the last update would win unless they use something (client-side) such as compare and set.
PUT and DELETE are just HTTP verbs and don't directly have anything to do with REST. You can support all verbs and have a garbage REST implementation, and (while obviously more difficult) have a great REST implementation for a handful of verbs.
You can use tools like Fiddler, or browser's built-in HTTP viewers, to observe interactions between your application and the server.
At a minimum, error codes and verbs help these tools highlight different behavior and problems. A 4xx class error, which usually means that your client-side application did something wrong, or that your user did something wrong, is very different than a 5xx class error that means that something really screwed up in the server.
Thus, the response codes make it very easy to use a 3rd party tool to diagnose malfunctions, even when the 3rd party tool doesn't know much about the application.
Likewise, at a minimum, a GET request is a read and doesn't change state. This is also useful when using a 3rd party tool to diagnose an application that runs over HTTP.
I do think that the article points out just how confusing proper REST can be. The semantics don't always match what the API is actually doing, either. Perhaps it's best to just limit oneself to the GET and POST verbs, 200, a few 4xx error codes, and 500. Perhaps it's also best to assume that rest semantics are for diagnostics and not for application level control?
I liked that the article made me think of using websockets for a pure JSON API, but I think it misses a lot of what is nice about rest and much of what it criticises is actually HTTP..... Rest as a set of verbs that act on resources is really useful.
I used to find it awkward to implement services in rest, as in some action that is triggered and may overlive the request cycle until I started thinking of service commands as items in a work queue that get processed by a worker. So when a service is requested I can see it as a resource being created.
In my opinion, you can't really understand REST until you understand HATEOAS - the two concepts work together and REST (and the restrictions it imposes) isn't really very meaningful without HATEOAS.
Twilio Conference 2011: Steve Klabnik, Everything You Know About REST Is Wrong: http://vimeo.com/30764565
> A REST API must not define fixed resource names or hierarchies (an obvious coupling of client and server). Servers must have the freedom to control their own namespace.
I'm not getting it. We have an API layer serving both mobile and web clients. When we change the API layer, we have to be careful to not remove any fields willy-nilly that mobile might be using. Instead we hard-deprecate mobile versions and remove fields later. It keeps the application stable but makes future architecture depend on past architecture.
Server instruction on URL construction seems to be doing a lot of work in order to not fix the problem. It does not buy us the ability to just switch around field names and relations and hierarchy without concerns for what consumers were using the old system.
That's the real problem with server / client coupling, not that the client needs to magically know which route a created resource has. Sticking a link in the response body just seems silly.
Without reinventing SOAP in JSON form, by this I mean providing machine-readable schema information via the API, I can't see a way through this. But even that wouldn't solve the problem, you'd need some kind of intelligence on the client side for managing an API that might shift around under it without warning.
If we change a field from createdDate to createDate, is there a way to use HATEOAS to communicate the name change?
It's just saying that the "URLs" are not fixed in the client (aside from the one root URL) and are provided by the server and dereferenced from content types.
> If we change a field from createdDate to createDate, is there a way to use HATEOAS to communicate the name change?
No. In REST/HATEOAS, the content types are fixed and documented, the hierarchy is mobile. Content type alterations impact clients which may not be generic over type contents.
I might be unlucky but I've personaly never encountered a single REST API that implements HATEOAS (among many third party APIs I've integrated into softwares I've been working on on).
If almost nobody who implements a REST API has HATEOAS in mind, doesn't it mean that REST is de facto independent from HATEOAS, no matter what the initial theoretician said about what REST should contain ?
In other words, if REST mean something different for almost everybody than REST for the author (and a minority of people aware of the author's first intention), then in my opinion it doesn't mean that everybody is wrong about REST, it just mean that the word «REST» has evolved to a slightly more relaxed definition.
Using GET/POST/PUT/DELETE with a defined semantic, the confidence that GET is idempotent, and the proper use of HTTP status codes.
Back in 2005, it was really common to have only GET routes even for update of deletion, or worst: to have a single url: http://example.org/action which concentrated all the API surface, different behavior being triggered by the type of the payload (JSON or even XML). Also, all the errors where `200 OK` but with a payload which contained the error. It was all done on top of HTTP but nothing was really using the HTTP tools (route + method + status code).
Every single API / webservice had its own logic & semantic, working with 3rth party was a nightmare … It's exactly this kind of mess that the modern trend of «non-dogmatic REST» really solved.
> If it's just doing HTTP, why not call it HTTP?
Is it really REST ? No.
Is everybody calling it REST ? Yes.
Can we change how everybody calls it ? I don't think so, and I don't really think it matters.
Many things are poorly named[1], but as soon as it gets to the popular language
we need to use it for what it mean for people, not for ourselves.
[1] Is a «quantum leap» a nano-scale step forward ? Where is the isomorphism in an Isomorphic web app ?
> Using GET/POST/PUT/DELETE with a defined semantic, the confidence that GET is idempotent, and the proper use of HTTP status codes.
That's literally got nothing to do with REST though, that's straight out of RFC 7231 (sections 4 "request methods" and 6 "response status codes") and the IANA HTTP Method Registry.
- Technically REST and HTTP are two different things, I totally agree with you.
- Historically, before REST became popular, people where doing complete nonsense on top of HTTP, with no respect of the spec whatsoever (see my comment above). This madness was stopped because of REST ! It's only when REST gained in popularity that people started to learn HTTP, and since then people developed a lot of semantically valid HTTP interface and called them REST API.
To sum up my previous points : REST as imagined by Roy Fielding never caught, and the word REST is now almost unanimously used to describe «HTTP-compliant API». May HATEOAS rest in peace :)
I think what bothers me most about REST is that the endpoint is not sufficient to get started. The schema is never known. I hate SOAP and xml-rpc, but at least you can know for sure what endpoints, parameters, and variable types are appropriate. With REST, you must have documentation or source code of the service you communicate with, they offer no discoverability.
I won't use REST again. I got an opportunity to use GraphQL recently in my profession and all of my projects will be using it in the future.
REST without using hypertext data types is indeed non-discoverable. You have experienced why REST is almost pointless without HATEOAS. Next time, look into using REST with HATEOAS, as it was intended to be used.
Previously using HATEOAS, gathering large amounts of data, say some kind of reporting dashboard, required a great deal of seperate HTTP requests, it was far less efficient in I/O and performance than without.
Anyway, I find GraphQL provides this solution very kindly, I can ask questions about the great big world, and request only specific fields, like a user's name, the names of their 10 closest friends and their availability status, all in a single call.
With HATEOAS this could be 10 to 20 calls, and maybe contain extra information in the response I'm not necessarily interested in.
I was looking for someone to mention graphql... For lots of cases this is a great way to reduce the client calls and give the client exactly what it is asking for..
> I think what bothers me most about REST is that the endpoint is not sufficient to get started. The schema is never known.
If you are actually doing REST, the interpretation of a resource representation is fully specified by the media-type (insofar as if there is additional schema, etc., information necessary, how to find that given the actual representation is also defined by the media type.)
Obviously, this is not true in the all-to-common REST-minus-HATEOAS.
You can sprinkle links/rel and use custom/vnd mime types (and include links to the correct json or xml schema) and then a developer can figure out how an API works just from an endpoint, yes ..
but that's not what this person is saying. The thing about SOAP is that it is very concrete and a standard. Yes you get implementation glitches/bugs here and there, but for the most part, you have a standard definition for an object and a standard way to describe it.
It's so standard you can point a debugging tool like SoapUI at it and it will construct a nice little form for filling out all the objects you want to pass with the correct types.
There are other terrible things about SOAP and it's difficult to version/add functions/update/blah blah, but it was concrete.
You could create tools to auto-discover all the paths in HATEOAS implementations, but it's still not quite as concrete as SOAP. Most people don't and rely on documentation to build clients with the right schema/requests/types. REST/HATEOAS are concepts and you document your formats, marshallers, etc. SOAP/WSDLs describes the entire data-interchange in a much more concrete format.
As much as I hate SOAP, I wish we had a more concrete interchange standard that wasn't as terribly complex.
Swagger is a decent middle ground. There's a lot of warts, but it's serviceable and fairly prevalent with implementations in a variety of languages. Mainly I like to use the yaml version to quickly communicate rest api's. I've also recently started appreciating JSON Schema more recently for this reason. It's lighter weight than xml schemas. Inclusion of regex based field validation is pretty handy.
Here's the rub, you're completely right, the problem is for the most part when you don't have rockstars making JSON Pure APIs you end up with half of HTTP redone in some god awful manner.
I once worked with an API where they implemented their own HTTPS and because their own https didn't support gzip they removed quotes from json keys to save bandwidth. JSON pure probably is better when working with knowledgeable people but REST is better than what most people come up with and when not following REST
The promise of APIs is simple. Send some data, something happens, get some data back.
But at about hour 4 of wrangling a bearer token to authenticate your barely-documentated PATCH request that is returning a strange error about your application/x-www-form-urlencoded body, you start to realize that APIs in theory are very different from APIs in practice.
(That being said, I don't love the "solution". It's very simplistic and it seems like the author doesn't really understand what he dislike about APIs. I don't think we need another protocol, but rather higher-level tools for dealing with them.)
Seems like most of the comments hate on REST because it's been poorly implemented by an API developer. Why is the solution yet another API protocol (JSONpure) and not stricter enforcement? (Idealistic i know...)
The point about SOAP not requiring documentation makes no sense either. You'd still need to document what the underlying fields in the various endpoints are. (We build against a lot of terribly documented SOAP APIs and its pure torture)
In terms of PUT (and PATCH) not being extensively used - it comes down to your use case. For the idempotent micro-services we build APIs against, there is a massive difference in the behavior expected for POST/PUT/PATCH and it would be pretty burdensome (and limiting) to have to create parsing code on the server for POST.
Ever notice how nobody calls their API “RESTpure”? Instead
they call it “RESTful” or “RESTish”. That’s because nobody
can agree on what all the methods, payloads, and response
codes really mean.
These reasons have nothing to do with why people don't use the term "REST" versus using "RESTful". RESTful is the compromised approach, cribbing some of the concepts outlined in Fielding's paper but dispensing with others. Among those are a de-emphasis of linking, and a url naming pattern. HTTP verbs describe types of actions in RESTful lingo, versus meaning something about the different idempotency & safety guarantees of a request in the REST paper.
In REST, I'm not sure that a lot of these issues are that contentious. I do think that some of the emphasized points in "RESTful" design practice can create more contention in API design, but that's the downfall of that one pattern, it has nothing to do with what Fielding described.
No governing body - at least to my knowledge - has convened to set things straight
IANA has a ton of info on link relations and they're thoroughly speced. IETF has tons of API / REST related specifications. Profiles allow for defining what your data means, there's open source curated lists of these profiles already so if you were designing an API you could even leverage existing works to make your design easier.
Roy is probably a great guy and he certainly had a lot of
great ideas. However, I don’t believe that RESTful APIs was
one of them.
This statement is just downright hysterical given the relative disparity here. So much of the web is owed to Fielding's paper, there's been countless books and blog posts and just human man hours devoted to the work he's done. Who's this guy? Why is this such a trend in blog posts in this community, it just looks foolish and comes off as petty...
> Ever notice how nobody calls their API “RESTpure”? Instead they call it “RESTful” or “RESTish”.
Isn't that just because RESTful is a play on words?
> For example, most web browsers have limited support for PUT or DELETE.
Really? How? If anything browsers restrict these methods to exactly how they should be used (DELETE can't have postdata but PUT can).
It's true that folks don't use PUT/DELETE much (the alternative works perfectly well though), but to me that's because they're unnecessary complexity, not browser support.
In the second article the author explains what a 'JSON pure' api would function. It completely throws out the OSI model and provides no way for the application layer to react to transmission errors, which HTTP codes provide.
Most of the problems described with REST in this article are examples of REST implemented improperly. We've had years to get it right; things like HTTP verb support, debugging, discoverability are all by and large a solved problem. The one point that stands is that it is deeply tied to HTTP, but I consider that to be a positive: a well designed REST API means the message is only about the content of what it's serving and not about negotiation of that content.
Here in the "JSON Pure API" you see a reinvention of HTTP request and response concepts built into the API payload, leaving the implementation of negotiation up to the consumer of the API. You lose all the benefits of years of development that have gone into browsers and web servers to handle this for you.
The main problem with REST is that people tend to call any JSON endpoint they build a REST API (and hence the term, "RESTful") which leads to a misunderstanding of what REST actually is.
Right, there's a great many blog posts that can be TL;DRed as "We implemented REST wrong, and it didn't work. I guess REST is overrated."
There's two major components that makes an API truly REST, as opposed to the XML-RPC and SOAP-style APIs that were popular in the early 2000s: Proper use of the HTTP verbs, and the use of Hypermedia.
Most so-called RESTful APIs have adopted the verbs part of it successfully and correctly, but the vast majority have completely whiffed on hypermedia.
Your HTTP API is a state machine whether you like it or not. Hypermedia gives you a means to describe the state transitions as a part of your API. Without it, you are essentially requiring each of your API consumers to re-implement the state transitions for themselves. (The aggravating part of that, however, is that there's not too many good hypermedia-based client libraries, because it seems that most of the proponents would prefer to navel-gaze in their ivory towers, thinking about RFCs and getting the standards perfect. But I digress.)
I'm not sure I see the advantages. It's a lot more verbose, based on the few examples I'm seeing there, and strongly reminds me of SOAP, XML Schema, and the rest of that over-complicated stack.
I suppose some amount of complication would be fine if the benefits were clear, but I feel like I could implement a client and a server for the less-verbose API that you start with, in the amount of time it would take to implement a server alone with all those bells and whistles. And I can't think of any scenario where they would actually add value.
I think the reason why RESTful APIs with very simple JSON payloads became so popular is because they get the job done with so little effort and so few abstract concepts to grok. This feels like a step backwards in that respect.
> Most of the problems described with REST in this article are examples of REST implemented improperly
If so many people get an idea wrong, then there is a problem with that idea.With SOAP or JSON/XML-RPC, there is a normative spec, and your implementation either passes the spec or it doesn't, so something is SOAP or it isn't and it is provable. There is no spec describing what exactly is REST and what isn't. You can't demonstrate something is or isn't REST in a strict fashion.
A dissertation is not a spec, it is a discussion. Roy Fielding never wrote a REST or a HATEOAS spec. which led to you complaining about how people get them wrong. They didn't get anything wrong, they took some of his ideas and rejected the REST because nobody can tell them what is REST and what isn't.
New mobile-first products should consider GraphQL over REST. There's a lot of benefits that you will probably end up doing yourself in a bastardized version of REST anyways, like field restrictions and multiplexing multiple unrelated data requests over the same network call.
Did I missed something on the article, whereas, I was hoping that it would expound on why REST should not be trusted. A title more apt would be:
"REST is totally flawed" or something similar.
Saying REST is a big lie is somewhat misleading, when the overall context of what it is and what it should be is still up for debate.
Does it matter when you can't completely and fully define what REST should be, but you are out there building awesome products while the rest of the web world is still up in arms on what it has to be?
I think REST is a perfectly acceptable and well-adopted pattern. There's no lie to it. I think GraphQL could displace it but adoption will be key.
What I am sick of with REST APIs is having to code them from scratch in dynamic languages each time and hook up all that laborious plumbing!
I read in an O'Reilly book on the subject that good REST APIs are declared. To that end I've been looking to tools like PostgREST, PostGraphQL, Swagger, and the ill-named Servant. Define the data, declare the resource routes, and you're good to go; generate the server stubs, the client code, and the documentation from the specification.
You don't get that from adopting a new standard every few years.
1) Almost every gripe in it refers to bad implementations, not bad specs.
2) It doesn't even mention HATEOAS. I'm no fan, but usually arguments about whether your API is REST or not revolve around how/whether you've done HATEOAS.
3) The rest of it is pulp tech writing that sounds like it was vomited out to meet some kind of publishing deadline.
Case in point:
> Consider, for example, when we might use the 200 OK response code. Should we use it to indicate the successful update of a record, or should we use 201 Created?
Here's a clue - read the spec! (SPOILER ALERT: the word "Created" is the giveaway). To quote:
200 OK
The request has succeeded. The information returned with the response is dependent on the method used in the request, for example:
<snip>
201 Created
The request has been fulfilled and resulted in a new resource being created.
"2) It doesn't even mention HATEOAS. I'm no fan, but usually arguments about whether your API is REST or not revolve around how/whether you've done HATEOAS."
You know that. I know that. But all the comments down to this point in the discussion have been over whether GET, PUT, POST, etc., are necessary or sufficient.
…and having implemented HATEOAS in a service (via json+hal), we’re moving far away (GraphQL) because of versioning, payload weight, and lack of flexibility. I’m sure there are things we could have done better, but the reality is that our clients need things that work differently than a “proper” REST/HATEOAS service.
We tried. We failed (insomuch as delivering a working service is failure, but we know it can’t grow the way we want it to grow because the payload weight is far too big). I’m not sure if it was us, or the fact that REST can’t map to everything we want it to be (it can’t, see the attempts to model actions performed to objects like IIRC fishworks did), but we are moving on.
Like any other architectural model, REST is good for some things, not for others. Versioning and payload weight seem like weird problems to have, though. Seems like JSON might have been a poor encoding for your use case.
By the way, do you have a link to that work by fishworks?
Any sufficiently complex data model will run into an issue where you need a mechanism to selectively render resources differently for different purposes. Putting new routes in place is a heavyweight way of doing this, and query-parameter mechanisms is a real pain. GraphQL started because RESTful APIs at FaceBook were causing great pain for their mobile clients (multiple round trips for data, full data sets, versioning issues on server and client). We experienced the same problem for similar (but smaller) datasets.
I did a quick look for the fishworks commentary, but I can’t find the discussion (this was from before the Borgacle consumption of Sun) about how much of a mismatch it was to implement VM controls through a REST interface. Is it legit to POST /vm/:id/restart or should it be a PATCH /vm/:id with a payload of { "action": "restart" }? Or…
Many advocates of a particular programming style (OO, REST, TDD are some of the more vocal, but FP advocates are right in there, too) seem to adopt the view that it is appropriate for everything. There’s definitely some impedance mismatch if you try to be REST “pure“ between that and the real world, the same as there will be if you go “pure“ for OO or FP for the same sort of things, but there will be different impedance mismatches.
I really tried with HATEOAS, because it makes sense, but the overhead has turned out to outweigh the costs for everything we’ve needed.
It does, it's just at a different level. REST is not a protocol, it's a set of architectural constraints, but it's well defined. Only one of the constraints (code-on-demand) is optional. HATEOAS isn't, since you need it to achieve the Uniform Interface that allows you to decouple the clients from the services.
I think the first comment/reply to the post hits the nail on the head, by Florian Klein[0]:
> Awesome! You replaced REST with REST. How revolutionary:
> Instead of transferring application state through the wire via one of its representations,
> you know transfer its state through the wire via one of its representations.
> Do I need to go any further?
> I think so, because to me your confusion comes mainly from the vocabulary you seem to misinterpret. You didn't even talk about hypermedia or links! That's kinda strange in an article about REST.
> Even tho I agree this vocabulary can be confusing, you should not throw the stone on the wrong subject (REST).
> Your problem is HTTP, right?
> Rest is not tied to http at all, and your point about making response bodies self contained is an honorable idea, but it doesn't change anything to your application being RESTful or not.
I work building, debugging, deploying and integrating JSON-formatted RESTish web API's every day. I find purist API's to be the most painful to use, and I find people who take the this-is-pretty-much-RPC-over-HTTP approach to be the second most painful unless it's perfectly built for my use-case.
There is a perfect middle-ground for most API implementations and really it comes down to the architects and software engineers implementing the API being able to think like API consumers and thinking of most use cases for their API's up front, then having a good level of "80% of people will use it this way, so we'll try and cater to the masses but support the other 20% like this".
There are definitely the marketing types who sell REST as the be-all-end-all solution to APIs, and all the other bells and whistles that go along with it. That isn't unique to REST.
I'm not on a mission to appease 100% of all use-cases for an API or integration. Such a solution will never exist and people trying to make out like there must be some sort of "holy grail" of API definition and design out there and %insert_current_fad% is wrong! No. We're doing our best, and today's API's with their API Test Consoles and their interactive walk-through's for people new to the API are a hell of a lot better than what we had before.
On first pass, I totally agree with the author. I haven't reviewed the proposed alternative yet but fingers crossed.
That said, I think he misses the single biggest issue with REST APIs that I continuously encounter and which has caused me to consider them sub-par. Representative "State" Transfer. REST APIs are only good for transferring around the state of stateful objects.
However, CRUD operations are only part of the equation in most modern software. Much of what we do is performing actions on those stateful objects (or, better yet in the microservice world, avoid state altogether). REST provides no identifiable mechanism for performing actions outside of CRUD operations and is, therefore, a completely impractical solution. Most real companies' attempts to build a "RESTful" API just end up being RPC over HTTP dressed up to look like REST.
REST provides no identifiable mechanism for performing actions outside of CRUD operations and is, therefore, a completely impractical solution.
The mechanism is identifiable once you start to really think in REST terms. The problem is that people think in RPC, and so try to shove its model instead.
REST is based on names (resources), not commands. Therefore, we must implement our actions as resources. Instead of having a "transfer()" command, you have a Transfer resource type, which you create to start one. Eg:
POST /transfers ... (Body describes parameters)
201 Created, Location: /transfers/34
This change from a command to a resource additionally provides the benefits of REST, necessary for communication over an unreliable network: rather than keep your connection open while the action is processed, you get an URL you can poll to check if it is finished. This works even if the client goes offline for some time.
To add to my previous post: it's not like this is a weird concept; every e-commerce site out there implements this. Imagine if we followed the RPC model: the user would click on "submit", and then the browser would wait for a reply when the order was finished being delivered - multiple days later!
Obviously this is impractical, so people follow the natural REST model: they create an Order resource, then send you a link with which you can follow the status of that resource.
But bring the "API" word and suddenly all of the preconceptions push developers to implement everything as function calls.
223 comments
[ 3.0 ms ] story [ 296 ms ] threadAnd right there, at your final sentence, you basically described why REST has more or less failed.
GET and POST are useless for implementing a complete application protocol. You'd basically overload these http verbs to the point where you would implement your own protocol. And that's what most people do anyway. You choose to not use PUT, some other person chooses to not use PATCH or HEAD and I choose to curse vehemently every time I have to use someone's service.
REST is nothing but loosely connected guidelines that nobody uses in the same manner.
The REST API I had to forward through however had no good documentation, no client library, so I was forced to write json serializers and reverse engineer the code. Overall, when you have a well written SOAP interface (rare, admitted), development time can be greatly reduced.
I learned SOAP relatively recently, but well after it was a fad. Today, my experience would be like yours if I had to make a SOAP service with just a WSDL. But when I started out? It would take a longer for me to wrap my head around all of it. I can't imagine how confusing it would be if I had to do it all without the benefit of working on a team whose focus is a SOAP-based product. I dunno if I would know where to begin.
Compare that to REST. Even if you know next-to-nothing to start, you can do a basic REST tutorial for just about any stack in an hour, and get a basic implementation of an API up in an afternoon.
Also, you don't seem to have looked terribly hard, because there are a few really powerful tools out there for autogenerating server and client code for REST APIs, as well as mock servers and a whole host of other tooling (See: Swagger, RAML, API Blueprint for starting points).
I've used a variety of tools to generate and test REST interfaces in the last ten years. To a mixed success, I must say.
Could things be better? No doubt. But REST (or something like it) is largely "the way things are built" these days and most people don't mind. Calling it a failure is quite a stretch IMO.
How many browsers do you have? 3-5?
How many REST client libraries are there?
Answer: one per service(per programming language).
What kind of protocol is that?
OK, I get what you're saying. Problem is that as far as I can see REST is perfect for S3-like services, Maps(?) and slightly more than basic CRUD applications.
You are bound to discover its limits very soon. The gazillions of books and blogposts out there heralding it as a serious interface are not helping either.
BTW, I don't know about other people criticizing, I am definitely not a purist. But after ~10 years of dealing with REST in various capacities(startups to Enterprises), I am a bit tired and can't wait for something to replace it.
GET and POST are all you need: "Return representation of available operations" and "apply this operation". It's the lambda calculus applied to the web (see Waterken's web-calculus for a more formal treatment).
You might say that this is too anemic a foundation and you want more built into the protocol level to handle some common tasks, but I'm not convinced it's necessary or even desirable. At some point requirements will change and some of those tasks will be supplanted, but we'll have to live with them forever if we bake it into the protocol.
I can do you one better. If you managed to reduce everything down to GET and POST here's an idea; just use POST for everything. Boom. You just re-invented SOAP.
How? Perhaps you should actually elaborate your argument. REST doesn't depend on the use of verbs, it's an architecture that elaborates the requirements for object designation (URLs), object lifetimes (statelessness) and hypermedia-driven service discovery (HATEOAS). Only GET and POST in HTTP are required to fulfill these requirements. If there's actually something wrong with that, then lay it out.
> If you managed to reduce everything down to GET and POST here's an idea; just use POST for everything. Boom. You just re-invented SOAP
Except you can't in a world with side-effects. You could do exactly what you say if every POST were guaranteed to be idempotent. Every request could carry a full payload like a POST request and a unique identifier to ensure at-most-once semantics. That would be a fine protocol, and totally REST compatible. What's the problem exactly?
Finally, SOAP carries far more baggage than you imply. It's a false equivalency.
When you encapsulate most of your operations under POST you basically create your arbitrary protocol. No assumptions can be made about your service. You can make your own assumptions about your own service, but the others can't.
> That would be a fine protocol, and totally REST compatible. What's the problem exactly?
The problem would be that it wouldn't be REST compatible. You should clearly read a few books on the subject. Friendly advice, not a snarky comment.
REST already has idempotent mutating operations, like PUT and DELETE. It's not just GET that's idempotent. So clearly the problem is that you redefine your own protocol, with your own semantics, even though we already have plenty of standardized methods/response codes.
> If there's actually something wrong with that, then lay it out.
You have obviously missed a ton of bibliography on the subject. Before reading random blog posts from random people who have their arbitrary assumptions about what REST is, I'd suggest reading a few books on the subject.
Honestly sorry if I sound snarky, but after 10 years on working with such APIs, and after reading countless books on the subject, it never ceases to amaze me how people still think that GET and POST are enough. But I don't blame you, but the browsers who basically broke the protocol by just using those 2.
And you shouldn't make such assumptions, you should just use the input parameters exposed in hypermedia which you obtained from a public service entry point. It's called encapsulation and that's REST. Again, what's the problem? All I hear is complaining that REST doesn't work the way other architectures work. Big surprise.
Certainly REST's HATEOAS can sometimes make a service less efficient as compared to some alternatives (so it can preserve encapsulation and support upgrade), but that's not the claim you're making. You're claiming some kind of insufficiency.
> The problem would be that it wouldn't be REST compatible. You should clearly read a few books on the subject. Friendly advice, not a snarky comment.
I've read Fielding's thesis, thanks. I understand REST perfectly well.
> REST already has idempotent mutating operations, like PUT and DELETE. It's not just GET that's idempotent.
So what? PUT and DELETE don't have the necessary semantics. GET representation, apply operation listed in representation via POST. What more do you need?
> Honestly sorry if I sound snarky, but after 10 years on working with such APIs, and after reading countless books on the subject, it never ceases to amaze me how people still think that GET and POST are enough
You still haven't pointed out a single reason why GET+POST are not enough or how they "break REST". I'm not asking for "a ton of bibliography", I'm asking for a single example. An existence proof that my claim is false. It should be trivial if this shit ton of bibliography exists.
Frankly, most of this vaunted "bibliography" since Fielding's thesis has been non-REST crap. It's amazing how easily people can misunderstand a 150 page thesis.
Nothing wrong with that, but don't call it a standard and don't try to name it something it isn't.
But is that really a huge problem?
Look at more rigorous rpc standards with more rigorous standards and formal interface definitions: RMI, xmlrpc, CORBA, SOAP, Thrift, AMF... I'm sure there are loads and loads of real world systems using these and they have their place, but REST has succeeded in a large niche that they have not.
It's useful to remember that REST was borne and adopted mostly in reaction to SOAP and XMLRPC (which in turn were basically replacing CORBA and RMI to work around the firewall). XMLRPC was too loose, and SOAP was too formal (way too formal). REST hit the sweet spot.
However, it's sad that the result was often that people just retooled their crappy SOAP / RPC systems to use decent URLs and called it REST. My litmus test is usually "returning 200 OK on all calls" - if you're doing that, that's not REST. Use proper HTTP return codes and put additional error messages in the payload, it's not hard. Also, if you have a job queue, give each job a URL with the ID and GET that to retrieve status.
I don't see a problem with this. In fact, I'd love it if everyone accepted this instead of whining that something isn't truly "RESTful."
For instance, the app I'm working on deliberately does not implement HATEOAS. I appreciate the academic effort behind REST and RESTfulness, but ultimately I view it only as an ideal to tend toward. As you said, it's a guideline.
There's usually a dollop of RPC in most APIs - and there's nothing wrong with that - but the 'pure vision' of REST is similar to the 'pure vision' of the Semantic Web. It's a dream for the next life not something we will receive in this one.
> I have full confidence that the authors considered these ideas, not laws.
"The authors" considered hyperlinking to be the one core concept of REST, all the rest is just fluff/transport concerns: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte... (that's the bloke who wrote the original REST paper).
That's like saying the authors of the word "bicycle" considered it being two wheeled idea, not law, and you'll call your 8-wheeled ATV a bicycle because it has wheels and you think wheels are nice and solve your problem and the religion department is down the corridor.
Yeah wheels are nice and solve your problem, your motorised monstrosity is not a bicycle though.
To my mind the benefit of REST purism was that it killed SOAP. A similar thing has happened at other stages of tech development (e.g. CSS purism cured us of all those awful <table> excesses).
The purism was a mistake and the details were wrong but it was necessary to get everyone behind a common goal - getting rid of something worse.
Most people don't understand REST. It is not a standard, it is not a set of practices. It is an architectural style and the web is built on it.
You can choose to follow the style (which is so much more than naming methods and URIs) or fight it. The dissertation is pretty clear about it[2], but most people ignore it because there are no code samples.
[1]: http://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post (REST creator talking about the PUT misconception)
[2]: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm (Full REST dissertation)
And most people chose to ignore it -- and implement RESTful (mostly unrelated to REST as described by Roy) APIs, and no much harm has befallen them.
Ignoring REST is impossible, the web is built on it.
- The uniform interface is in every URI (if you use them, you use REST).
- The code-on-demand constraint is everywhere (if you use JavaScript, you're using REST).
- Hypermedia is everywhere (if you have links on your web page, you're using REST).
- The client-server constraint I don't even have to bother explaining (although WebRTC might bring P2P back in the game).
- The layering is everywhere (if you do haproxy, varnish, squid or similar, your using REST).
The _RESTful API_ thing is just a myth. People needed a name to discourage tunneling RPCs over HTTP, so they invented these loosely defined terms to push the idea. It should be called HTTPful, because it tells more about avoiding re-implementing HTTP features than it tells about the REST style.
This can also be solved by futures. Any POST that you'd like to retry, which will be any of them given the unpredictability of network partitions, can be bound to a future so the operation is applied only once and all future attempts simply return the bound value.
And it's not always safe to retry POSTs. If POST is an insert, for example, retrying it would produce two inserts. And this can have interesting consequences when processing responses. Suppose that you have sent a POST request, but before you could read the response, connection dropped. You didn't get a chance to read the status code, so you don't know if your insert succeeded or not. If it didn't, you want to retry - but you'll need to do a GET first to check the current state of affairs. OTOH, if you're doing a PUT, you can just retry immediately without re-checking.
My previous post already covered idempotent POSTs via futures. The fact is, only the application can decide whether a POST is safe to retry arbitrarily or must be made safe by binding to a future. The PUT is merely a small optimization that is now obviated by the spread of HTTPS.
Idempotence can be useful knowledge for client-side caches, so HTTPS doesn't obviate the value of the PUT (or, for the same reason, DELETE) vs. POST distinction.
And yet you don't provide a single concrete reason. And even go on to say the non-REST way you use REST at your team.
>REST is one of the more successful strategies we've come up with for connecting systems, this is just another case of letting perfect stand in the way of good enough. Using GET for non-destructive operations and POST for updates and deletes is a nice, portable compromise. I've been trying hard for years to find a reason to bother with PUT, but so far I've found it not worth the effort.
Note how none of this (or even few parts of what the author of TFA described) is actually REST as defined by Roy.
It's like reading a book on building a house and using ideas to build a shed. Sure your shed has electricity and a sink but it's still a shed, not a house.
Same with terms like RESTful. You don't call your shed a "house like building" as it's missing key pieces of a house.
REST requires HATEOAS. The only real implementation is the world wide web. Everything else is really JSON-RPC or some other protocol with a few ideas borrowed from REST.
https://www.youtube.com/watch?v=8pTEmbeENF4
Re-implementing those same semantics in your own messaging protocol / format, without intertwining the concerns of the protocol and the message format, throws away any/all of those benefits. You need a protocol that guarantees that middleware can "look inside" the messages it's passing (or at least their metadata), in order for any of this to work. That's why HTTP has both a transparent part (req path+headers; resp status code) and an opaque part (req and resp bodies) to each message: the transparent part is there for data that affects middleware behavior, while the opaque part is there for data that doesn't.
Note that that doesn't mean you're stuck with HTTP1. SPDY/HTTP2 is effectively an entirely different protocol—but it keeps the same semantics of requiring certain properties of the metadata tagged onto each message at the protocol level, so that anything that speaks the protocol can use that metadata to inform its decisions.
It assumes that the middleware supports HTTP properly.
Come on, person.
I don' know about you, but I provide REST stuff where the only option is update.
GET and POST are all you really need for REST.
1. Pure read.
2. Impure (stateful) read.
3. Idempotent write.
4. Any other write.
There's no particular reason to separate inserts, updates, deletes etc as part of the protocol - they're all just different kinds of writes, and middleware doesn't derive any benefit from being able to distinguish them. Thus, this can be a part of the payload.
On the other hand, the difference between reads and writes, and the two subdivisions within each, do matter for purposes such as caching and automated error recovery (e.g. a proxy can repeat an idempotent write a few times before returning the error to the originator of the request).
In REST, we have GET for #1 and #2, PUT and DELETE for #3, and POST for #4. In practice, this is often simplified to just POST used for both #3 and #4, but that loses a valuable distinction (but is unfortunately often necessary because of the lack of support for other methods). On the other hand, the PUT/DELETE distinction is largely pointless.
POST requests can be made idempotent by binding the result of processing that request to a future, so every subsequent request simply returns the already computed result.
Impure reads are the default, and pure reads are designated by long-lived cache headers, ie. it's an impure read that lasts as long as the server responds.
So really you just need GET and POST, and server-side frameworks should make POST requests idempotent by embedding some notion of futures for side-effecting operations. See the Waterken server for the first development platform to really get this right.
e.g. Instead of saying "Insert a transaction for £20", you say, "Insert a transaction that entity A calls 1234, for £20".
Stripe use something like this to ensure that as long as you call their API to ask for a payment and use the same key, they won't charge the person twice.
https://stripe.com/docs/api#idempotent_requests
Not sure what you mean by client-generated. The server-side app generates the id because it has to store and interpret it. This can be as simple as a sequence number, similar to how TCP guarantees delivery. It depends on the schema really.
This is the simplest way to ensure you can perform arbitrary retries of POST in case of a network partition.
This data doesn't even need to be integrated with your app's schema, although that's ideal so you can manage the storage lifetime. But you could use an entirely separate store for GUIDs and cached replies, and so it becomes transparent to your app and just becomes another layer.
Per the description above:
"Each non-idempotent operation is tagged with a unique identifier"
Since the operation originates on the client, the client has to tag it with the identifier, no? And the server has to store this identifier in a way that associates it with any data affected by that operation in a non-idempotent way.
Or are you saying that the client first has to make a round-trip to the server to generate the ID, and then use that server-provided ID for the actual POST?
This is always the case for REST given HATEOAS, ie. you've already made some hypermedia requests to obtain the URL of the endpoint to which you will POST.
Unless the resource you're posting to actually is the public entry point of your service, but that would be very unusual.
Generally speaking, what is the flow like? Suppose I allocated myself an endpoint, but then never posted anything to it - what does the endpoint actually contain then, if queried? Do unused ones get "garbage collected" somehow eventually?
Not necessarily. The numbers don't have to be stored before they're actually used by clients. For instance, you could return a simple integer, like an object version #, and an HMAC(integer, resource URL) to ensure the client can't tamper with it. You only store data under that integer when the user successfully POSTs to that resource for the first time.
> Generally speaking, what is the flow like? Suppose I allocated myself an endpoint, but then never posted anything to it - what does the endpoint actually contain then, if queried?
There are many possible designs here. I prefer something like this in CRUD-like contexts [1], because it gets me a fully auditable change history, optimistic concurrency control and all the storage needed is fully integrated into the app schema in a sensible way.
Combined with the HMAC described above, you don't need to preemptively allocate any storage for idempotent POSTS and you can use simple integers as your unique identifiers. So a POST against a version number that's not the latest version would simply return the version that followed if their POST was the one that succeeded, or a redirect to the latest version if someone else had updated it.
Hopefully you can imagine various relaxations on this to make other trade offs. For instance, a much simpler approach would be to return GUIDs for each possible POST, and you just store each GUID associated with the object when a POST succeeds. If the object's current GUID is the GUID the user is posting, return the current data with 200 OK, otherwise return a 301 Moved to a URL referencing the latest version and let the client try to apply their updates to that. The storage can be reclaimed after a suitable period of time; say a month if your app is for browser clients
[1] https://higherlogics.blogspot.ca/2015/10/versioning-domain-e...
By "pure" here I mean that we're talking about a pure function of its inputs.
Why distinguish? Because if you know that the results are not affected by server state, they can be cached much more aggressively.
PATCH allows two users to update different fields on the same resource at the same time with no conflicts. Otherwise, they'd use PUT and the last update would win unless they use something (client-side) such as compare and set.
Is this just referring to using semantically correct HTTP status codes for things like caching, or is there more to it that I'm missing?
edit: And also, and perhaps most important, what about REST makes it easier to take advantage of the transport layer's advantages?
edit 2: This article has answered some of my questions and brought more clarity: https://philsturgeon.uk/api/2017/01/26/graphql-vs-rest-cachi...
At a minimum, error codes and verbs help these tools highlight different behavior and problems. A 4xx class error, which usually means that your client-side application did something wrong, or that your user did something wrong, is very different than a 5xx class error that means that something really screwed up in the server.
Thus, the response codes make it very easy to use a 3rd party tool to diagnose malfunctions, even when the 3rd party tool doesn't know much about the application.
Likewise, at a minimum, a GET request is a read and doesn't change state. This is also useful when using a 3rd party tool to diagnose an application that runs over HTTP.
I do think that the article points out just how confusing proper REST can be. The semantics don't always match what the API is actually doing, either. Perhaps it's best to just limit oneself to the GET and POST verbs, 200, a few 4xx error codes, and 500. Perhaps it's also best to assume that rest semantics are for diagnostics and not for application level control?
Um...is this guy trying to implement REST clients with HTML forms? Does he know about ajax? Fact check: http://stackoverflow.com/questions/165779/are-the-put-delete...
I used to find it awkward to implement services in rest, as in some action that is triggered and may overlive the request cycle until I started thinking of service commands as items in a work queue that get processed by a worker. So when a service is requested I can see it as a resource being created.
Twilio Conference 2011: Steve Klabnik, Everything You Know About REST Is Wrong: http://vimeo.com/30764565
REST APIs must be hypertext-driven: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
Hypermedia APIs - Jon Moore: http://vimeo.com/20781278
Designing a RESTful Web API: http://blog.luisrei.com/articles/rest.html
HATEOAS is for Humans :(http://intercoolerjs.org/2016/01/18/rescuing-rest.html)
Rescuing REST From the API Winter: (http://intercoolerjs.org/2016/05/08/hatoeas-is-for-humans.ht...)
> A REST API must not define fixed resource names or hierarchies (an obvious coupling of client and server). Servers must have the freedom to control their own namespace.
I'm not getting it. We have an API layer serving both mobile and web clients. When we change the API layer, we have to be careful to not remove any fields willy-nilly that mobile might be using. Instead we hard-deprecate mobile versions and remove fields later. It keeps the application stable but makes future architecture depend on past architecture.
Server instruction on URL construction seems to be doing a lot of work in order to not fix the problem. It does not buy us the ability to just switch around field names and relations and hierarchy without concerns for what consumers were using the old system.
That's the real problem with server / client coupling, not that the client needs to magically know which route a created resource has. Sticking a link in the response body just seems silly.
Without reinventing SOAP in JSON form, by this I mean providing machine-readable schema information via the API, I can't see a way through this. But even that wouldn't solve the problem, you'd need some kind of intelligence on the client side for managing an API that might shift around under it without warning.
If we change a field from createdDate to createDate, is there a way to use HATEOAS to communicate the name change?
It's just saying that the "URLs" are not fixed in the client (aside from the one root URL) and are provided by the server and dereferenced from content types.
> If we change a field from createdDate to createDate, is there a way to use HATEOAS to communicate the name change?
No. In REST/HATEOAS, the content types are fixed and documented, the hierarchy is mobile. Content type alterations impact clients which may not be generic over type contents.
What does a mobile hierarchy buy me?
Edit: nevermind, I think I can see the idea. Thanks!
If almost nobody who implements a REST API has HATEOAS in mind, doesn't it mean that REST is de facto independent from HATEOAS, no matter what the initial theoretician said about what REST should contain ?
In other words, if REST mean something different for almost everybody than REST for the author (and a minority of people aware of the author's first intention), then in my opinion it doesn't mean that everybody is wrong about REST, it just mean that the word «REST» has evolved to a slightly more relaxed definition.
This is also the claim of this talk: https://www.youtube.com/watch?v=6UXc71O7htc
If it's independent of HATEOAS what is in REST? If it's just doing HTTP, why not call it HTTP?
Using GET/POST/PUT/DELETE with a defined semantic, the confidence that GET is idempotent, and the proper use of HTTP status codes.
Back in 2005, it was really common to have only GET routes even for update of deletion, or worst: to have a single url: http://example.org/action which concentrated all the API surface, different behavior being triggered by the type of the payload (JSON or even XML). Also, all the errors where `200 OK` but with a payload which contained the error. It was all done on top of HTTP but nothing was really using the HTTP tools (route + method + status code).
Every single API / webservice had its own logic & semantic, working with 3rth party was a nightmare … It's exactly this kind of mess that the modern trend of «non-dogmatic REST» really solved.
> If it's just doing HTTP, why not call it HTTP?
Is it really REST ? No.
Is everybody calling it REST ? Yes.
Can we change how everybody calls it ? I don't think so, and I don't really think it matters.
Many things are poorly named[1], but as soon as it gets to the popular language we need to use it for what it mean for people, not for ourselves.
[1] Is a «quantum leap» a nano-scale step forward ? Where is the isomorphism in an Isomorphic web app ?
That's literally got nothing to do with REST though, that's straight out of RFC 7231 (sections 4 "request methods" and 6 "response status codes") and the IANA HTTP Method Registry.
- Technically REST and HTTP are two different things, I totally agree with you.
- Historically, before REST became popular, people where doing complete nonsense on top of HTTP, with no respect of the spec whatsoever (see my comment above). This madness was stopped because of REST ! It's only when REST gained in popularity that people started to learn HTTP, and since then people developed a lot of semantically valid HTTP interface and called them REST API.
To sum up my previous points : REST as imagined by Roy Fielding never caught, and the word REST is now almost unanimously used to describe «HTTP-compliant API». May HATEOAS rest in peace :)
Accepting the redefinition of terms merely because they are popularly misunderstood is literally putting the inmates in charge of the asylum. wink
I won't use REST again. I got an opportunity to use GraphQL recently in my profession and all of my projects will be using it in the future.
Anyway, I find GraphQL provides this solution very kindly, I can ask questions about the great big world, and request only specific fields, like a user's name, the names of their 10 closest friends and their availability status, all in a single call.
With HATEOAS this could be 10 to 20 calls, and maybe contain extra information in the response I'm not necessarily interested in.
If you are actually doing REST, the interpretation of a resource representation is fully specified by the media-type (insofar as if there is additional schema, etc., information necessary, how to find that given the actual representation is also defined by the media type.)
Obviously, this is not true in the all-to-common REST-minus-HATEOAS.
but that's not what this person is saying. The thing about SOAP is that it is very concrete and a standard. Yes you get implementation glitches/bugs here and there, but for the most part, you have a standard definition for an object and a standard way to describe it.
It's so standard you can point a debugging tool like SoapUI at it and it will construct a nice little form for filling out all the objects you want to pass with the correct types.
There are other terrible things about SOAP and it's difficult to version/add functions/update/blah blah, but it was concrete.
You could create tools to auto-discover all the paths in HATEOAS implementations, but it's still not quite as concrete as SOAP. Most people don't and rely on documentation to build clients with the right schema/requests/types. REST/HATEOAS are concepts and you document your formats, marshallers, etc. SOAP/WSDLs describes the entire data-interchange in a much more concrete format.
As much as I hate SOAP, I wish we had a more concrete interchange standard that wasn't as terribly complex.
A simple reusable class library of request and response entities is easy to provide in multiple languages.
I once worked with an API where they implemented their own HTTPS and because their own https didn't support gzip they removed quotes from json keys to save bandwidth. JSON pure probably is better when working with knowledgeable people but REST is better than what most people come up with and when not following REST
But at about hour 4 of wrangling a bearer token to authenticate your barely-documentated PATCH request that is returning a strange error about your application/x-www-form-urlencoded body, you start to realize that APIs in theory are very different from APIs in practice.
(That being said, I don't love the "solution". It's very simplistic and it seems like the author doesn't really understand what he dislike about APIs. I don't think we need another protocol, but rather higher-level tools for dealing with them.)
The point about SOAP not requiring documentation makes no sense either. You'd still need to document what the underlying fields in the various endpoints are. (We build against a lot of terribly documented SOAP APIs and its pure torture)
In terms of PUT (and PATCH) not being extensively used - it comes down to your use case. For the idempotent micro-services we build APIs against, there is a massive difference in the behavior expected for POST/PUT/PATCH and it would be pretty burdensome (and limiting) to have to create parsing code on the server for POST.
In REST, I'm not sure that a lot of these issues are that contentious. I do think that some of the emphasized points in "RESTful" design practice can create more contention in API design, but that's the downfall of that one pattern, it has nothing to do with what Fielding described.
IANA has a ton of info on link relations and they're thoroughly speced. IETF has tons of API / REST related specifications. Profiles allow for defining what your data means, there's open source curated lists of these profiles already so if you were designing an API you could even leverage existing works to make your design easier. This statement is just downright hysterical given the relative disparity here. So much of the web is owed to Fielding's paper, there's been countless books and blog posts and just human man hours devoted to the work he's done. Who's this guy? Why is this such a trend in blog posts in this community, it just looks foolish and comes off as petty...Isn't that just because RESTful is a play on words?
> For example, most web browsers have limited support for PUT or DELETE.
Really? How? If anything browsers restrict these methods to exactly how they should be used (DELETE can't have postdata but PUT can).
It's true that folks don't use PUT/DELETE much (the alternative works perfectly well though), but to me that's because they're unnecessary complexity, not browser support.
JSON-Pure is not much more than an encoding. RESTful is an entire protocol.
but timeless
Here in the "JSON Pure API" you see a reinvention of HTTP request and response concepts built into the API payload, leaving the implementation of negotiation up to the consumer of the API. You lose all the benefits of years of development that have gone into browsers and web servers to handle this for you.
The main problem with REST is that people tend to call any JSON endpoint they build a REST API (and hence the term, "RESTful") which leads to a misunderstanding of what REST actually is.
There's two major components that makes an API truly REST, as opposed to the XML-RPC and SOAP-style APIs that were popular in the early 2000s: Proper use of the HTTP verbs, and the use of Hypermedia.
Most so-called RESTful APIs have adopted the verbs part of it successfully and correctly, but the vast majority have completely whiffed on hypermedia.
Your HTTP API is a state machine whether you like it or not. Hypermedia gives you a means to describe the state transitions as a part of your API. Without it, you are essentially requiring each of your API consumers to re-implement the state transitions for themselves. (The aggravating part of that, however, is that there's not too many good hypermedia-based client libraries, because it seems that most of the proponents would prefer to navel-gaze in their ivory towers, thinking about RFCs and getting the standards perfect. But I digress.)
I wrote a blog post a few months back that goes into more detail about the advantages conferred by a true Hypermedia API: http://blog.theamazingrando.com/in-band-vs-out-of-band.html
I suppose some amount of complication would be fine if the benefits were clear, but I feel like I could implement a client and a server for the less-verbose API that you start with, in the amount of time it would take to implement a server alone with all those bells and whistles. And I can't think of any scenario where they would actually add value.
I think the reason why RESTful APIs with very simple JSON payloads became so popular is because they get the job done with so little effort and so few abstract concepts to grok. This feels like a step backwards in that respect.
If so many people get an idea wrong, then there is a problem with that idea.With SOAP or JSON/XML-RPC, there is a normative spec, and your implementation either passes the spec or it doesn't, so something is SOAP or it isn't and it is provable. There is no spec describing what exactly is REST and what isn't. You can't demonstrate something is or isn't REST in a strict fashion.
A dissertation is not a spec, it is a discussion. Roy Fielding never wrote a REST or a HATEOAS spec. which led to you complaining about how people get them wrong. They didn't get anything wrong, they took some of his ideas and rejected the REST because nobody can tell them what is REST and what isn't.
GraphQL handles these cases elegantly.
"REST is totally flawed" or something similar.
Saying REST is a big lie is somewhat misleading, when the overall context of what it is and what it should be is still up for debate.
Does it matter when you can't completely and fully define what REST should be, but you are out there building awesome products while the rest of the web world is still up in arms on what it has to be?
What I am sick of with REST APIs is having to code them from scratch in dynamic languages each time and hook up all that laborious plumbing!
I read in an O'Reilly book on the subject that good REST APIs are declared. To that end I've been looking to tools like PostgREST, PostGraphQL, Swagger, and the ill-named Servant. Define the data, declare the resource routes, and you're good to go; generate the server stubs, the client code, and the documentation from the specification.
You don't get that from adopting a new standard every few years.
1) Almost every gripe in it refers to bad implementations, not bad specs.
2) It doesn't even mention HATEOAS. I'm no fan, but usually arguments about whether your API is REST or not revolve around how/whether you've done HATEOAS.
3) The rest of it is pulp tech writing that sounds like it was vomited out to meet some kind of publishing deadline.
Case in point:
> Consider, for example, when we might use the 200 OK response code. Should we use it to indicate the successful update of a record, or should we use 201 Created?
Here's a clue - read the spec! (SPOILER ALERT: the word "Created" is the giveaway). To quote:
200 OK
The request has succeeded. The information returned with the response is dependent on the method used in the request, for example: <snip>
201 Created
The request has been fulfilled and resulted in a new resource being created.
You know that. I know that. But all the comments down to this point in the discussion have been over whether GET, PUT, POST, etc., are necessary or sufficient.
We tried. We failed (insomuch as delivering a working service is failure, but we know it can’t grow the way we want it to grow because the payload weight is far too big). I’m not sure if it was us, or the fact that REST can’t map to everything we want it to be (it can’t, see the attempts to model actions performed to objects like IIRC fishworks did), but we are moving on.
By the way, do you have a link to that work by fishworks?
I did a quick look for the fishworks commentary, but I can’t find the discussion (this was from before the Borgacle consumption of Sun) about how much of a mismatch it was to implement VM controls through a REST interface. Is it legit to POST /vm/:id/restart or should it be a PATCH /vm/:id with a payload of { "action": "restart" }? Or…
Many advocates of a particular programming style (OO, REST, TDD are some of the more vocal, but FP advocates are right in there, too) seem to adopt the view that it is appropriate for everything. There’s definitely some impedance mismatch if you try to be REST “pure“ between that and the real world, the same as there will be if you go “pure“ for OO or FP for the same sort of things, but there will be different impedance mismatches.
I really tried with HATEOAS, because it makes sense, but the overhead has turned out to outweigh the costs for everything we’ve needed.
REST will live on in memory, as an idea of a utpoia, just not in implementation.
Just because HATEOAS makes REST APIs better, doesn't mean those without the use of it aren't REST.
Even SOAP can be REST conform.
Anyway, I guess with the rise of GraphQL, which is more strict (at least in its definition) REST will go away and we will have better dev life's.
It does, it's just at a different level. REST is not a protocol, it's a set of architectural constraints, but it's well defined. Only one of the constraints (code-on-demand) is optional. HATEOAS isn't, since you need it to achieve the Uniform Interface that allows you to decouple the clients from the services.
> Awesome! You replaced REST with REST. How revolutionary:
> Instead of transferring application state through the wire via one of its representations, > you know transfer its state through the wire via one of its representations.
> Do I need to go any further? > I think so, because to me your confusion comes mainly from the vocabulary you seem to misinterpret. You didn't even talk about hypermedia or links! That's kinda strange in an article about REST.
> Even tho I agree this vocabulary can be confusing, you should not throw the stone on the wrong subject (REST). > Your problem is HTTP, right?
> Rest is not tied to http at all, and your point about making response bodies self contained is an honorable idea, but it doesn't change anything to your application being RESTful or not.
I work building, debugging, deploying and integrating JSON-formatted RESTish web API's every day. I find purist API's to be the most painful to use, and I find people who take the this-is-pretty-much-RPC-over-HTTP approach to be the second most painful unless it's perfectly built for my use-case.
There is a perfect middle-ground for most API implementations and really it comes down to the architects and software engineers implementing the API being able to think like API consumers and thinking of most use cases for their API's up front, then having a good level of "80% of people will use it this way, so we'll try and cater to the masses but support the other 20% like this".
There are definitely the marketing types who sell REST as the be-all-end-all solution to APIs, and all the other bells and whistles that go along with it. That isn't unique to REST.
I'm not on a mission to appease 100% of all use-cases for an API or integration. Such a solution will never exist and people trying to make out like there must be some sort of "holy grail" of API definition and design out there and %insert_current_fad% is wrong! No. We're doing our best, and today's API's with their API Test Consoles and their interactive walk-through's for people new to the API are a hell of a lot better than what we had before.
[0] http://disq.us/p/103w6z6
That said, I think he misses the single biggest issue with REST APIs that I continuously encounter and which has caused me to consider them sub-par. Representative "State" Transfer. REST APIs are only good for transferring around the state of stateful objects.
However, CRUD operations are only part of the equation in most modern software. Much of what we do is performing actions on those stateful objects (or, better yet in the microservice world, avoid state altogether). REST provides no identifiable mechanism for performing actions outside of CRUD operations and is, therefore, a completely impractical solution. Most real companies' attempts to build a "RESTful" API just end up being RPC over HTTP dressed up to look like REST.
The mechanism is identifiable once you start to really think in REST terms. The problem is that people think in RPC, and so try to shove its model instead.
REST is based on names (resources), not commands. Therefore, we must implement our actions as resources. Instead of having a "transfer()" command, you have a Transfer resource type, which you create to start one. Eg:
This change from a command to a resource additionally provides the benefits of REST, necessary for communication over an unreliable network: rather than keep your connection open while the action is processed, you get an URL you can poll to check if it is finished. This works even if the client goes offline for some time.Obviously this is impractical, so people follow the natural REST model: they create an Order resource, then send you a link with which you can follow the status of that resource.
But bring the "API" word and suddenly all of the preconceptions push developers to implement everything as function calls.