Problems with RESTful APIs (2015)
mmikowski.github.io
mmikowski.github.io
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.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.
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?
- GET, PUT, POST, DELETE (I learned there were others but were kind of niche/obsolete)
- 200s for success, 400s for client (request) error, 500s for server error.
It was all nice and worked great (and still does, years later).
But over time numerous people started told me that no it's actually all wrong for one reason or another. I've heard that I should never use anything except GET and POST. That I should ALWAYS return a 200 and provide error metadata as a response if there actually was an error. That POST is actually meant for updates and PUT is meant for new entities. That the opposite is true. That neither is true and I should always use POST for any mutation of state. etc.
I feel like I had success because I approached it from a position of ignorance, meaning I just implemented a simple, sane REST API and was none the wiser that I was doing it wrong.
None of it is REST though, it's just one more RPC over HTTP protocol, which is also what TFAA advertises. Though your version uses HTTP as more than a trivial transport which I guess is nice.
If this isn't REST then the Wikipedia page on REST needs updating or I'm just not explaining it well enough.
REST based on the Richardson maturity model[1] involves:
Level 0: Using HTTP as the transport protocol: e.g. SOAP
Level 1: Identifiable objects: e.g. /object/object_id
Level 2: Using HTTP as the application protocol: e.g. Using POST to create new objects and DELETE to remove them
Level 3: HATEOAS
[1] https://martinfowler.com/articles/richardsonMaturityModel.ht...
`/robots/robot_id/exceptions`
`/maps/map_id/destinations`
`/maps/map_id/areas/speed_limit_areas`
Performing operations is not done via. RPC but rather POSTing a new `mission` to the queue.
There's no HATEOS but that would generally be silly, since this isn't an API that requires easy discovery and consumption by third parties. I'm not sure I subscribe to the HATEOS required for REST, but I don't really care to argue.
I think I'm starting to get a sense that people can be really opinionated on this stuff, and I'm still lost as to what there is to gain by it. To suggest what I'm describing isn't REST would be to say that the first sections of the Wikipedia page are wrong. So are we so far off-base that we need to revise the Wikipedia page? Or is this more just an opinion?
Thanks for sharing your thoughts. Maybe there's a chance to de-mystify my confusion on why there's so many opinions on something that, to me, seems so simple to define.
Sadly the person you respond to is an idiot, their points 1 and 3 have literally nothing to do with REST. You could have all endpoints be /435645646 yet do rest, you can have the most beautifully crafted URLs in the world and do rpc, they're orthogonal concerns. Most people do the latter, incidentally.
> Performing operations is not done via. RPC but rather POSTing a new `mission` to the queue.
That's still RPC. Encoding your procedure calls via HTTP verbs doesn't make it not RPC, it makes it (as originally noted) leverage HTTP as more than a trivial transport.
> There's no HATEOS
So it's not REST, HATEOAS/hyperlinking is the one thing that qualifies your API as REST according to the bloke who originally defined that term: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
> I think I'm starting to get a sense that people can be really opinionated on this stuff
Well yeah imagine you see a nice essay defining or formalising a concept (hyperlinked application interfaces) and creating a word/acronym for it (REST), then you see the world around it coopt it without any of the meaning to qualify something which already existed but has seemingly fallen out of fashion (RPC in this case). That's bothersome.
> seems so simple to define.
If your simple definition of REST is just that you're using HTTP, why would you need a separate acronym for it?
"Somewhat misguided" is a lot less harsh and confrontational, FWIW. HN civility guidelines and all.
>> Performing operations is not done via. RPC but rather POSTing a new `mission` to the queue.
> That's still RPC. Encoding your procedure calls via HTTP verbs doesn't make it not RPC, it makes it (as originally noted) leverage HTTP as more than a trivial transport.
RPC uses POST, and sometimes GET, usually to a single URL. OP is creating, modifying, and deleting resources, each at its own URL, using the proper HTTP verbs. You might be getting hung up on the fact that the "mission" resource corresponds to something conceptual rather than something physical like an individual robot? Again, that's your own taste, rather than anything about REST. Or do you mean instead that OP should invent some new verbs appropriate to robots, like MOVE or ACTUATE? That would be a bit goofy...
NRRESTBTGTTERM.
Hmm, that doesn't really roll off the tongue. Maybe BetterREST.
It's not better and it still is not REST.
Why don't you just call it what it is: HTTP. Or maybe HTTP-RPC if you want to be more specific.
The reasons I have against it are that
1. I think it complicates the client because it needs to discover the api at runtime instead of just coding it up in a straight forward manner.
2. Receiving the capabilities seems to imply that these are the activities that can succeed. But they don't have to succeed. So you still have to handle errors. So you may as well know up front what the whole API is and handle errors, etc.
3. Dynamic apis are resistant to pipelining if you don't know what the next url will be.
But I'm here to learn, so please hit me with a clue stick and explain why REST sans HATEOAS is not better.
To be more specific, HATEOAS is an essential component to comply with the Uniform Interface constraint of REST, which, as the dissertation describes, allows for decoupling and independent evolvability of the client and server.
Since we still accept the idea that client libraries and the programs that use them should be completely coupled with the services they communicate with, and it's fine to force thousands or millions of developers to update their software because an URL on some service changed, HATEOAS doesn't feel particularly useful.
You mean like Electron applications? :P
But seriously, I don't know what kind of clients you want to use, but if I want to store data on an object store, for example, I know what the verbs are. And if a new one is added, then at some point I need to change something on the client side to factor that in. Unless the server is also serving the UI as they do with web pages.
<semi-rhetorical-strawman>If I'm using something like $AccountingProgram and my bank puts in a new possible action like "donate" to let me easily donate to charities which will return important information like deductions and the relevant fields, etc., then how might my accounting become aware of this new concept? </semi-rhetorical-strawman>.
Maybe I'm too troglodyte to see it. My engineering senses are tingling with excitement that it would be cool that it automatically gets through to the client (without also being open to click/UI hijacking from shitheads) but I just don't see how it can happen.
Still happens all the time in mobile world. Not as obvious in Desktop word because the site is the app, you just download it each time anew instead of once. But there are Chrome plugins for many sites - Chrome web store has a lot of them. Most of the sites can work fine without them, nevertheless they exist.
Huh. What does this abbreviation mean in this context? I'm at a total loss here, and the only relevant google result is this thread.
You did good job there. Ignore naysayers just because then they have to do more work to handle your correct error codes and actually send correct HTTP methods.
REST has (had?) a very specific meaning, as defined by Roy Fielding in his dissertation. People seem to be objecting against using the term 'REST' for things that are not REST in that sense. But of course that's just arguing whether you use the correct word for what you built, not whether what you built is the right solution for your problem. So if they are trying to argue that it isn't, then their argument is fallacious.
Well, you have it wrong with "not defining a protocol". You didn't define your protocol systematically, instead you have defined it ad hoc, but you still defined it.
> - GET, PUT, POST, DELETE (I learned there were others but were kind of niche/obsolete)
Really? You only have three modifying operations and one that reads the state? Or is it that you crammed all the others into an informally specified almost-RPC in a single POST request?
This is definitely the other way around.
The fact that the request-URI is to be the new home of the entity being PUT is the thing from which correct understanding of PUT is derived. Idempotence is a trivial consequence of that (so not necessary in its own right), and is not sufficient. Read the RFCs.
POST is meant for anything and everything, absolutely including updates. PUT is meant for writing-or-overwriting a complete or partial resource, at a URI that is the Request URI. In practice, for most applications, this makes PUT impractical for new entities (because the requester cannot know the correct URI for the new resource), but in some applications it can make sense, and either way there's more to it than you assert.
Can someone write this pamphlet?
I used to work for a place where people said exactly that. It was then followed with comments that anything other than GET and POST posed a security risk.
There's still a staggering amount of ignorance out there of HTTP; even amongst those who claim to be web developers.
There are a lot of them saying that your system is not pure REST, that it would be a joke to call it REST, that most "REST" APIs out there are not real REST and only they know the true way of doing stuff
If only they shipped something or made something work given real-world constraints
No.. So any creation or update can be a POST. If your operation is idempotent, then you can make it a PUT. If you take the subset of POSTS that are idempotent in your application, this is what could be made a PUT.
So a set operation foobar=50, would could be a POST, but since its idempotent, it could also be a PUT.
A increment operations foobar++, would have to be a POST, but could not be a PUT since it is not idempotent.
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.
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.
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
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.
Sure - everybody ends up reimplementing async jobs and polling... some people prefer XML/json/edn/etc... some people get pedantic on 3xx and non-200 2xx status codes... differing standards on referencing other objects/collections/etc... some people use POST where they should use PUT (or insist upon using PATCH and OPTIONS). It has just as many faults.
But it's wildly successful for are reason, and dismissing it probably is going to result in relearning a bunch of hard-earned lessons about integrating across lots of very heterogeneous systems and environments.
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...
First, it has nothing to do specifically with the mechanics of the HTTP protocol. There was an emergent pattern as people built APIs over HTTP, that they can re-use much of the semantics in common with HTML. HTML over HTTP naturally led to the definition of REST, where forms, semantics, and hyperlinks are not just an optional feature but a necessity.
Formal specifications, meaning hypermedia API media types are just emerging, Hydra[1] and Micro API[2] to give examples. Fielding wrote about REST in 2000 and about a decade later was rediscovered by industry, and I hope that two decades later, people will rediscover its utility for APIs. My interpretation is that Fielding did not "invent" REST, but rather formally described emergent behavior on the web at large. Implementations may have differed wildly but had many features in common.
The problems described in the article are the result of not following a media type suited for APIs. HTML is a wildly successful media type for machine-human interaction, there's no reason why there can't also be one or a few for machine-machine interaction.
More to the point, I think the original article's criticisms are pretty disingenuous. And his decision to ignore 'complicating factors' associated with network transport and caching: gee perhaps you're ignoring these because you CAN largely ignore these if you architect RESTful APIs. I mean c'mon, stuff like this makes me think the author is either very naive or very ignorant: The vocabulary of HTTP methods and response codes is too vague and incomplete to get agreement on meanings. No governing body - at least to my knowledge - has convened to set things straight.
Yes, yes they have. Remember SOAP? That's an OASIS "standard", it's highly specified in detail and it meets the author's desire for 'content' being independent of the transmission channel (you know, for when you want to implement a web API over two tin cans and a piece of string). He should just use that, or the OASIS ratified SOAP v2 (i.e. ebms3/as4), which is also 'transport neutral'. Have fun with that.
The rest of the criticisms basically boil down to "sometimes people don't implement it right" and "I don't understand HTTP response codes". There's really nothing that magical about REST. When you browse the web you are basically using a 'human-friendly' interface to a RESTful system. When APIs use the same architectural style it's the same thing, but for robots. That's pretty much it.
Point 1: 200 is shorthand for 2xx. If I'm too lazy what the code is for "forbidden" or "insert something fancy here", I just return a 400. Does it's job and underlines that it's the user's fault. ;)
Point 2: PUT and DELETE worked for me very well. I remember just one project where everything had to be "tunneled" through GET. Because "exotic" toolchain/frameworks, at least there was a canonical way to do so.
Point 3: I think that's actually the nice thing about REST that its vocabulary is limited. Thinking about the pletora of unstructured HTTP XML RPCs and tons of structurally different Highlevel JS APIs for each vendor, REST seams quite relieving.
Point 4: I don't really get that. Chrome Debug works awesome, I get all the information I need. There are many tools out there for mega comfortable debugging.
Point 5: That's definitely a thing. I wish the article was only around that point.
:+1 and they are also better than what author advocates. One thing in author proposal that absolutely puts me off is this:
> JSON-Pure APIs (...) have only one response code to confirm proper receipt of a message - typically 200 OK for HTTP.
This is terrible. PLEASE do not design your API-s like this, this will confuse the hell out of all bots, browsers and everyone who depend on status codes (and that's all web clients). Your 404 error pages will be cached and stored in google, redirects will not be remembered, error pages not retried, etc etc.
I don't get the idea of json pure. Author claims that one benefit is:
> All errors, warnings, and data are placed in the JSON response payload.
But REST-ful API doesn't forbid you from returning informative error messages in json. Why not keep old HTTP semantics known by everyone and return json with informative error message?
I also think that author confuses HTTP semantics as defined in actual WEB STANDARDS with purely academic work of Roy Fielding. Meaning of status codes or methods has nothing to do with REST-ful this is just plain HTTP semantics as defined by RFC-s.
Was ditching XML for JSON just due to cosmetic / trending reasons?
We still use HTML for markup. Why did everyone ditch XML for JSON beyond just treading reasons is an interesting question.
And everyone uses a web browser.
Ergo, if you develop an HTTP API, you should do it with JSON so it can work easily in web browsers.
Browsers had native XMLHttp support before they had JSON support.
The fact JSON (use to be) a subset of JavaScript and the browser runs JavaScript natively is not convincing.
Other than evil eval(jsonString) (before JSON.parse was available) which is basically asking for XSS, what benefit you get from JSON being consumable by JavaScript?
I think XMLHttp was available in browsers (in a vendor specific annoying way perhaps but still available) way before JSON.parse was available... am I missing something?
eval() was present from day 1 and is the reason JSON looks like it does. Obviously it requires complete trust in the source (historically, the same origin).
Limitations are good. I find it really easy to read. You can install browser extensions to make it even more readable.
Schema can come from a well written specification.
> Was ditching XML for JSON just due to cosmetic / trending reasons?
No, as said before, it's easy to write / read / generate / parse. No awkward DOM style management if you want to parse out a value. I really hated it with XML.
HTML is fine also for what it was invented for.
Most browsers can display XML readably by default.
> Schema can come from a well written specification.
That doesn't replace a schema though.
> No, as said before, it's easy to write / read / generate / parse. No awkward DOM style management if you want to parse out a value.
"DOM-style management" of XML documents which can be replaced by JSON is equivalent to hand-rolling a JSON parser from the raw bytes. It's not the hardest thing in the world, but it's not exactly easy either.
With most XML applications equivalent to JSON, that part would be tucked away in the relevant library, e.g. the XML-RPC serialisation format is almost isomorphic to JSON[0], and in Python converting between native objects and the XML-RPC serialisation is just `loads` and `dumps`[1] — though you don't usually have to do that at all since the XML-RPC client will handle the serialisation and deserialisation for you automatically — which is more or less what the JSON library provides[2].
And JSON is convenient in dynamically typed languages because it maps more or less directly to their native dynamic structures, that's not quite the case for languages like C++ or Haskell.
[0] null (nil) is an extension but it natively supports binaries and datetimes
[1] https://docs.python.org/3/library/xmlrpc.client.html?highlig...
[2] https://docs.python.org/3/library/json.html?highlight=json#b...
True, but a JSON string is already more readable than XML.
If you open your devtools it's inspectable by default: http://imgur.com/a/eW0Rv
> that's not quite the case for languages like C++ or Haskell.
So handling XML in those languages are easier?
BTW if your server / services feel more native with XML serialization / parsing to native data structures use that. Picking JSON just because everybody else does it is not a good idea.
However if you make a public web API consumed mostly by browsers (JS), then yeah, pick JSON and REST.
That also works for XML documents: http://i.imgur.com/NmcWdaO.png
> So handling XML in those languages are easier?
Both are "crap" since they're dynamic information which has to be brought into a statically typed world. However depending on the schema it might be possible to automatically generate the binding and hide the dynamic resolution.
> BTW if your server / services feel more native with XML serialization / parsing to native data structures use that. Picking JSON just because everybody else does it is not a good idea.
> However if you make a public web API consumed mostly by browsers (JS), then yeah, pick JSON and REST.
Agreed.
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...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.
> 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.
I have never, as in ever, stumbled upon this problem. So I googled it. It turns out that what he means is that HTML forms don't support PUT and DELETE. In a world where everybody uses JavaScript anyway, I cannot see how this is a flaw in RESTful API's. It might be a flaw in HTML forms though.
GET is easy.
HEAD is easy.
DELETE is easy.
PATCH is easy, especially when you use one of the two more useful standards (RFC 7386: JSON Merge Patch, or RFC 6902: JSON Patch).
PUT is not much use for large resources (like those typically found in business systems) since it requires you to provide every field, but usually you would want the back end to assign at the last the primary identifier, date created, etc. I seem to remember reading that even Roy felt PUT was not well designed.
POST is a catch all for any other update/insert type activity.
To paraphrase Winston Churchill, "http verbs are a poor system, but better than all the other systems that have been tried from time to time."
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.
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.
I can see a little of this. It's better today to send parameters in HTTP data in JSON format rather than encoding them in the URL. If you're doing a pure GET, you can send parameters with the URL, but anything that changes server side state probably shouldn't be done that way.
Of course, what's happening is that the JSON crowd is re-inventing SOAP, but, whatever.
SOAP uses schemas and the like, they just keep reinventing the same RPC as ever, except can't actually bring themselves to use the word. At least JSON-RPC is honest there, and ticks all of TFAA's box:
* uses whatever's under as a trivial transport (covers 1, 3 and 6)
* all data and metadata are part of the higher protocol (covers 2, 4 and 5)
* is JSON (covers the entire essay)
Actual innovation in this area seems to be limited to JS background data sync libs. Ironically, reference-capable protocols like CORBA anticipated this whereas flattening it all REST-style was a step backwards.
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.
So far so good.
> Roy advocated using the request methods he helped define in the HTTP standards to impart meaning to HTTP requests.
Not even close.
REST may be one of the most misunderstood ideas in all of computer science. As described in Fielding's dissertation, REST is a software architectural style whose main idea is that hypertext drives state changes, aka Hypermedia as the Engine of Application State (HATEOAS). Fielding leaves the transport protocol as an implementation detail.
In other words, an automated agent (API consumer) should interact with an API in the same way that a human interacts with a Web site. User browses to well-known URL. Page displays content with links. User clicks on a link. And so on.
A human doesn't need to read documentation on using any particular website any more than an automated agent should need to carry service-specific instructions on using an API. Media types and hyperlinks do all the heavy lifting.
The stuff about structured URLs and response codes came later, was created by others, and has almost nothing to do with REST's central idea. It's a different architectural style altogether.
From Fielding himself:
> I am getting frustrated by the number of people calling any HTTP-based interface a REST API. Today’s example is the SocialSite REST API. That is RPC. It screams RPC. There is so much coupling on display that it should be given an X rating.
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
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:
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.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.
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.)
I wrote a related article for Hacker Noon a few days ago which was trending on Reddit: https://hackernoon.com/rest-over-websockets-instead-of-http-...
It's interesting that an increasing number of developers are pushing the notion of using REST-like ideas over WebSockets instead of HTTP.
I fetch from a URI (http://example.com/meep/boris) and get back a response with Content-Type application/meep; version=3. My browser searches for a viewer for that content type. The content type defines the actions I can take on the content, either locally or talking to the server, just as it does for any other protocol passing data over the wire. That understanding has to be out of band for the model.
But to be truly RESTful, the viewers must also be accessible via hypertext. For example, the response with the content could include a link header to point me to a usable default viewer for the content type. So you have to have a content type that whatever you're using (browser, SPA in the browser, etc.) knows how to interpret as a handler for content types. Whether it uses PUT, PATCH, or BABOON in HTTP verbs should be irrelevant. That's part of the protocol of the content type handler.
It's that second part that's a problem. The security implications are a bit worrisome. And if you're shipping handlers only for your own data, you control all the pieces, so there's no point going through all the decoupling.
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
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.
What I'm trying to say is having more choices or more ways to do something isn't necessarily a good thing as it makes it easier for people to do it so many ways that they can screw it up or just make it weird for everyone else. REST is kind of weird that way and I agree with this article for the most part.
GraphQL handles these cases elegantly.
So when I see a blog article like the author, I think we should just hear him out, get what you can get out of it and either support him or let him be. Sure, he may not be perfect but at least he has tried scratching an itch where he saw a potential problem and looked for a solution. And the problem he has is actually shared by thousands of developers so he is definitely not alone.
Every couple years (hell, every couple months now), we face some new technology, or some new way of doing things and there is always the initial set of people who come across as being highly offended by it.
Like back in the days when XML was all the hot stuff and when JSON came out, most bypassed it stating it's not sophisticated enough, doesn't have any xpath support, bla bla bla, doesn't have a reference book must be not ready for enterprise. It was the same thing with SOAP when REST first came about. And these type of patterns repeats throughout the years, from frameworks, languages, and probably everything else.
People hate change. I think we all get that, it's just the way it is. However, over time the same people that were against it, slowly gives in to the same thing they were against the more people start talking or hears about it. I'm sure it happened to you at some point.
So folks, don't just judge a book by it's covers. Give it some time and perhaps even give it a try. RESTful may be good as it is for you now, but I'm sure you also know that it is not as good as it gets. There are those who believes there are problems with the RESTful approach we have now and looks for a new standard that solves them. They may be right and perhaps will come out with something we will all be using some day. Who knows.
Sometimes REST is that tool.
I also tend to combine JSON with REST. I still enjoy using proper HTTP codes when possible. So if you're sending a json payload to update an object that doesn't exist I'll give you 404. But at the same time you're able to create that object by defining its properties in a json payload in the next request and not some obscure url parameters or POST parameters.
I don't see anything wrong with using proper HTTP methods and return codes when possible.
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.
"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'm not saying there aren't answers to these questions, but doing any of these things in REST is not straight-forward.
So if we concede that people using these 2 operations are not implementing REST, what are they implementing? Well i would argue, CQRS.
GET = Query, POST = Command
Then our REST api becomes super simple and consistant across implementations.
/api/run POST UpdateModelCommand { } /api/run GET ListModelQuery { }
> The what-we-actually-indended-to-use request method embedded in the request payload, e.g. DELETE
Don't do this.
> The what-we-actually-indended-to-use response code embedded in the response payload, e.g. 206 Partial content.
Don't do this!
> If you’ve ever worked with a RESTful API, you know they are almost impossible to debug.
You're begging the question.
There exist plenty of APIs that abuse the HTTP methods and status codes, which I feel like is really the core argument being made. But completely ignoring it and what its purpose is is throwing the baby out with the bathwater. Read and understand the RFCs for HTTP, for a start; unfortunately, I'd wager that far too many devs of ostensibly RESTful APIs do not do this, and it shows when you get a response with a status code that makes zero sense. The vast majority of HTTP APIs I've interacted with violate both the semantic meaning of the methods and that of the status codes. (GitHub's is about the best I've ever seen.) A "RESTful HTTP API" is an API that uses the mechanisms in HTTP to accomplish the ideas of REST; (i.e., I'm not trying to equate HTTP and REST, I just think abuses of HTTP are a major impediment to understanding REST. Using HTTP well will naturally help you accomplish REST.)
> can anyone out there explained to me what 417 Expectation failed really means?
You've not read and understood the RFCs for HTTP. 417 Expectation Failed is obvious if you have; an expectation (on the request) failed (cannot be met by the server). An "expectation" is denoted on the request through use of the "Expect" header. The only existing expectation is 100-continue. Even if you do not know this by heart (and I don't expect that), it's readily findable:
1. Google "http rfc status codes"; unfortunately it's the second result; Google doesn't understand that the second result is an updated version of the first. Regardless, if you go for the first result, it points you to the second (-ish, b/c the RFC was split into multiple).
2. You select "417 Expectation Failed" in the Table of Contents.
3. You read the extremely straight-forward explanation. If you don't understand what the Expect header is for, the RFC links you to it.
So what are the ideas of REST? Start at its (de-)acronym: "Representational state transfer". That is, transfer of a resource. A "resource" is just an "object" or a concept, a thing — the actual concrete thing represented by a resource is going to be determined by your domain specific problem. E.g., "a user's profile data", "a message in a thread", "a news article" are all "resources" in that they embody some concept or idea that we want to communicate the underlying state of. You also need a standard, or uniform method of uniquely identifying, or locating these resources, which is what a URL is for (you then see why it's lit. uniform resource locator). So we build URLs to stand in as names for resources.
In order to transfer the state of a resource, embodied at a URL, you need to send it across a wire. You need to serialize it into some representation that's going to get transferred. That's what HTTP is supposed to help you do.
If you were writing a RESTful API, embedding things like the status of the operation in the response body should feel wrong, because the status isn't conceptually a part of the resource you were trying to operate on in the first place; go back to our example of "a post in a thread" — whats a status got to do with that? While technically, yes, HTTP's entity body is capable of transferring arbitrary binary data, the end result of using it that way results in simply the re-invention of wheels, such as needing to signal the success or failure of operations on resources. HTTP's purpose, alongside the ideas of REST, is to pull out the common bits that occur when writing code that transfers representation of stuff around, such as, e.g., caching, getting an ok to transfer large content prior to writing it all out to the wire, knowing the status of the operation, or pagination of collections of resources. (I cannot count the number of times I've witnessed API designers reinvent pagination, badly!)
The manner in which people like to use HTTP, with effectively only GET and POST (maybe!) is more akin to RPCs to me. It works. You can do that. But you then need to handle caching, pagination, status of operations, etc. on your own, and you'll end up, I believe, reinventing HTTP. Doing a lot of that (I think, and I think this was Roy's original point) is more effective if you structure your operations around transferring representations of resources around; this is especially visible in caching, because in caching you need the representation of a resource, because that's what a cache works with by its very nature. (As opposed to, say, making opaque method calls on a remote instance.)
Go read [1]; nothing really in there is bound to HTTP, just that HTTP makes a lot of it easier. Also, while I understand that Roy has a lot of arguments around how representations should be hypertext — and I agree with them, mostly — I think that comes second to the ideas that:
1. A URL represents a resource
2. The point of GET / PUT / DELETE is to transfer the state of that resource.
If you don't understand those two points, I don't think you'll understand the arguments behind hypertext.
[1]: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch...
The other points,
> They are easy to debug since transaction information is found in easy-to-read JSON inside the payloads using a single, domain specific vocabulary.
Pushing everything into an opaque blob removes the ability for any tooling to pull out high level information. Chrome devtools, httpie, etc., all disprove this point.
> Problem #1: There is little agreement on what a RESTful API is
I agree. I also feel like too many people who think they know have not read anything from Roy Fielding, or even the HTTP RFCs.
> The REST vocabulary is not fully supported
depends mostly on
> most client and server applications don’t support all verbs or response codes for the HTTP protocol. For example, most web browsers have limited support for PUT or DELETE. And many server applications often don’t properly support these methods either.
This isn't true: JavaScript in all browsers in respectable use supports this; Android and iOS fully support HTTP; most server-side development languages have excellent tooling for this. This is a completely false statement, and requires proof, or at least a concrete example to back it up. (Were it true, it only invalidates the use of HTTP as an aid to accomplishing REST.)
> Problem #3: The REST vocabulary is not rich enough for APIs
POST is, essentially, a catch-all for odd operations not supported by other verbs.
> Imagine we create an application where we want to send a “render complete” response back to an HTTP client
If we have a resource that represents a rendering job, if you GET a representation of that render job, it can include some indication of completeness. The bigger problem here is actually HTTP's polling, IMO. Websockets might serve this specific example better, but this singular example doesn't invalidate that most web APIs boil down to CRUD $object of $type, which HTTP supports phenomenally well.
> Problem #5: RESTful APIs are usually tied to HTTP
Well, yes. At the end of the day, it has to be tied to something. HTTP is a pretty good something, with decent tooling.
> They use only one response code to confirm proper receipt of a message - typically 200 OK for HTTP.
Yes, you can send a single bit back. HTTP attempts to be a bit more rich than this. E.g., if something is in progress, and attempting to retrieve the data I just stored will fail until some serve-side job is complete, HTTP can easily signal this. Muxing them into 200 OK removes that information.
> They completely separate the response content from the transmission mechanism. All errors, warnings, and data are placed in the JSON response payload.
HTTP already has this: the response content is the body of the response. The transmission mechanism is HTTP. I don't want errors, warnings, etc., in the payload, where they are opaque and unusable by common tooling.
> They can easily be moved or shared between transmission channels such as HTTP/S, WebSockets, XMPP, telnet, SFTP, SCP, or SSH.
These channels do not support transferring the state of something. (Okay, HTTP does.) telnet is a mostly dumb pipe, same for SSH. You would need to build some custom, non-iteroperable layer on top of that. HTTP is the standardized version of that.
[1] http://128.232.0.20/teaching/0809/DigiCommI/tennenhouse1989l...
JSON-Pure is not much more than an encoding. RESTful is an entire protocol.
but timeless
Interestingly there's yet a deeper problem with fully RESTful APIs (Hypermedia APIs), where REST's Stateless Protocol constraint combined with HATEOAS creates an API where clients need to undergo multiple HTTP round trips to load the data they need. For example, suppose your app lets users browse movies. You might have a sequence like:
client: "hey, I'm gonna act like a browser and hit api.com and take it from there" GET api.com => { "movies": { "rel": "content/movies", "href": "/movies" } }
client: "hmm, ok I guess I'll click the movies link" GET api.com/movies => { "items": { "count": 4, "prev": null, "next": "/movies/page/2", [ {"href": "/movies/1"}, {"href": "/movies/2"}, {"href": "/movies/3"}, {"href": "/movies/4"}, ] } }
client: "ok, I guess I'll fetch each of those movies (I kinda wish the server had just told me what those contents were in the first place)" GET api.com/movies/1... etc. => { "href": "/movies/1", "rel": "self", "title": "Waterworld", "image": "/images/waterworld.png", } ...
And don't forget the client-side logic to join/order all this data and handle errors. This problem is called "underfetching" and it's present in true REST APIs by design. Ironically, many "RESTful" APIs break from the REST constraints specifically to avoid this problem.
Another great article on REST APIs: https://martinfowler.com/articles/richardsonMaturityModel.ht...
Out of curiosity, do you know of any examples of RESTful APIs that use a protocol other than HTTP (say like IMAP or NNTP)?
Before REST, there was SOAP, similar in spirit to the JSON-Pure solution proposed by this author. SOAP's promise was a version of Java's "Write once, run everywhere". In the case of SOAP, this meant that if you have a SOAP client, you could consume data from any SOAP server with only the domain specific part different.
Like Java, SOAP over-promised. In practice, there was horrible incompatibility between all the different SOAP providers and consumers; people lacked features so they hacked it on to the protocol, only to discover later that the default SOAP client in $THAT_OTHER_LANGUAGE didn't allow them to consume that hack as easily as it was in the first language. And so on, and so forth.
REST, on the other side, hardly promises anything at all. In practice, most people doing a REST API agree on a rough idea of what URLs look like, and yes let's do our best and embrace HTTP verbs and status codes. In a way, REST is "learn once, use everywhere" - not unlike React Native's motto.
This became wildly successful because the clients were all compatible from the start (after all, HTTP was widespread already). Compared the SOAP and most RPC setups, the clients are super underpowered; you need to do a bit of extra work. The only way to know what URLs to compose is to read the API docs (because HATEOAS is beautiful in theory only). The data is often JSON but maybe not, and you're again going to have to pay attention to the docs.
In practice, though, it keeps the developer firmly in control. Most developers using REST actually understand the entire protocol. They know enough HTTP to be dangerous, they can look at what goes over the line and it makes sense. The moment you add more features to the protocol, you just make it more complicated and obtuse.
I'm not convinced that's a way forward, not without serious (GraphQL-level) benefits.