8 ms·
It's interesting that both of these guidelines kind of reject HATEOAS by mandating explicit versioning. It seems that HATEOAS was never really a thing. It's jus
by camus2 10y ago
It's interesting that both of these guidelines kind of reject HATEOAS by mandating explicit versioning. It seems that HATEOAS was never really a thing. It's just too complicated to implement in practice. In that sense, REST in practice has always been just RPC without a clear spec for procedure call like XML or JSON RPC.
- einrealist 10y agoI think, there is just too much bias involved. At least thats what I am experiencing. Not using HATEOAS ever, but complaining about it makes me angry. My preaching: If you can write a client by using a semantic document format (e.g. HTML, XML+XSD, Json-Ld), you end up with a more elegant and stable implementation. And as a provider of such an API, I spend more focus on the surfacing domain than the structure of my resources. It makes me sad, that even Google does not try.
- veesahni 10y agoI wrote about API design (with a similar rejection of HATEOAS): http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#hateoas http://www.vinaysahni.com/best-practices-for-a-pragmatic-res... In short: humans can follow links, even as a website goes through significant changes. Code can follow links, but can't make clear independent decisions when significant changes happen to the API. [Updated for clarity]
- johnjuuljensen 10y agoCode can follow links as well, as long as the semantics doesn't change. Aside from versioning through mimetypes, which I believe is a really bad idea, I find HATEOAS to be a beautiful concept, although not very useful in practice. It's a good place to start though. Trying to design for that can help you shape your API properly, just like SOLID or TDD can do for code.
- mateo411 10y agoWhy do you think versioning through mimetypes is a bad idea?
- johnjuuljensen 10y agoI should probably have moderated that statement, but mostly I think it's bad because it makes the versioning aspect inaccessible from the lowest common denominator, the browser address bar. Versioning through the url and versioning through mimetypes requires the same amount of work from the user, but the former is a lot simpler. If you then also take into account, that many http clients have poor support for manipulating headers (SAP and PowerShell (earlier version) for instance), then choosing mimetype versioning makes it harder (impossible) for your users.
- mateo411 10y agoI also prefer putting the version in URL. I find it to be practical and easy way to version your API. I've also been told that it's not the right way to do it.
- scaryclam 10y agoThere's no "right" or "wrong" way tp version APIs. There's only peoples opinions. I'd suggest that if someone is saying you're doing it wrong by putting it in the url, you should probably learn to ignore them as they can't tell the difference between their own preference and facts.
- JimDabell 10y ago> mostly I think it's bad because it makes the versioning aspect inaccessible from the lowest common denominator, the browser address bar. That also rules out using any HTTP method other than GET. The browser address bar doesn't seem relevant here, and if it were, then it would rule out the vast majority of APIs. Versioning through the URL breaks interoperability of clients using different protocol versions. If a client using v1 communicates with a client using v2, then they will see two separate sets of resources and they would never have the same identifiers for (what should be) the same resources.
- tofflos 10y agoThank you for your write-up on API design. It's well-written, concise and to the point. I spent quite some time reading it while learning best practices about REST API design last year.
- veesahni 10y agoI'm happy the post helped you :)
- zerocrates 10y agoIt's just never been clear to me what HATEOAS is really supposed to be good for. Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? The general idea of returning links to related resources and/or actions is fine and good, but the rhetoric tends to go further, to ecompass claims like the API being "self-documenting" or amenable to a universal client. It always seems to me that this Big Idea of just presupposes the existence of a "smart" client that can really understand the links, one that there doesn't seem to be much sign of. GitHub's API proudly notes its use of hypermedia and URL Templates in its responses, but I still have go read the documentation to decide what link I need to use, and what needs to fill into those variable slots in the URLs. The template doesn't do much for me that text in the documentation saying "these GET paramters are accepted/required" wouldn't just as well.
- deleted 10y ago[deleted]
- squeaky-clean 10y ago> Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? I've never understood this either. My API client isn't smart enough to follow links and write logic for me, so when they say "the client" can "discover", they must be referring to myself, and not my code? Well I'd much rather read documentation than click hyperlinks inside an API.
- SEJeff 10y agoFWIW, Roy Fielding's paper[1] on REST (where the word comes from) was very specific that a REST api is a hypermedia/hypertext based api, and that if it isn't hypermedia, it isn't REST. He clarified[2] this later on. This isn't from some internet toughguy, but the guy who literally coined the phrase. Sadly, his implementation was also all XML so gross, but you get the idea. HATEOS is just an implementation of a JSON based hypermedia api. Me? I'm a fan of grpc for everything. HTTP/2 > HTTP1 and binary compressed protobuffers > deflate compressed (gz) json. http://grpc.io http://grpc.io [1] https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc... [2] http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
- deleted 10y ago[deleted]
- jauco 10y agoIf I get it correctly HATEOS is about the following: Say you're building a standardised API (with many consumer implementations _and_ many provider implementations all talking to each other). In that case making stuff like the layout of a url or even the protocol over which the data is retrieved part of the specification is putting a needless strain on your API providers. If an API provider uses a shared webhost or a specific framework he might not be able to follow that structure, or it might be harder then necessary. If instead, your specification only specifies the document layout (Roy Fielding calls it the "media type") then it's easier for people to implement your api. People usually have full control over the document contents. If you don't design your API like that it's not a REST Api according to Roy Fielding. If your API is not going to be implemented by many providers and many consumers all talking to each other in countless permutations then there's not much use in following all of REST[1]. (And also not much use in calling your API a rest api) Of course the word REST now means something else then Roy Fielding intended for it. I have no problem with that. I believe he did at some point. [1] I don't remember the url or the exact quote, but I believe I read a piece by him where he said literally that REST as he described it is only useful for the many2many consumer/provider use case. I might be mistaken.
- webmaven 10y agoIt even cooler than that: You only have to standardize the types and meanings of the links, the actual implementations can vary in the locations of the endpoints, but the structure of the documents can too, and the client(s) will be smart enough to figure out that on this server they need to retrieve /users/mike/products/, and on that server they need to get /userproducts/mike/all/, just through the fact that the representation of the user (also probably retrieved from different locations) on each server has a link labeled rel="all products" pointing to the right place, regardless of what else was included or omitted from the representation, so you can have interoperability on whatever is standardized even if implementations of both clients and servers have different capabilities they expose. So, as long as you standardize the semantics and relations, the URL layouts and the document layouts can be quite different, in the same way that you know when looking at a page what the button or link labeled "Home" will do, regardless of the exact location on the page or the fact that on one server it takes you to /, on another to /index.html, and on yet another to /main/home/ .
- vfaronov 10y ago> In that sense, REST in practice has always been just RPC without a clear spec for procedure call like XML or JSON RPC. HTTP, even when used without hypermedia, still has interesting features that are not found in traditional RPC. For example, you can’t just stick nginx in front of your gRPC server and tell it to cache stuff. You can’t tell your Thrift client to retry all idempotent requests automatically (without enumerating the functions that are idempotent). Not to mention upcoming things like HTTP/2 push and 103 (Early Hints). I like to think that HTTP is less of a leaky abstraction over the network.
- KuhlMensch 10y agoWeb frontenders in my experience want REST APIS that are semantically thought out (aka "nice") rather than compliant with some spec. ...HATEOS, IDGAF if //api.me.com/article/list uses 404 to mean there are zero articles returned from an otherwise valid resource. Just yesterday, I asked a back-ender to put the total_pages, page_limit, and current_page on their endpoint. BE: But you should be able to use my "self", "next", "prev" links? FE: Well the thing is, I want to generate and render links for every page BE: Oh, I see...
- friendzis 10y agoAs I see it, HATEOAS by providing API structure dynamically depending on application state, restricts the application to non-concurrent use and full backward compatibility, because application state perceived by the client and the actual state might diverge in concurrent use (either concurrent clients or state change by code upgrade). It is impossible to build a client (which does more than query a resource in a loop and simultaneously does the right thing) that will magically know about newly available link if application state changes between getting the resource, making a decision and following a link based on that decision. Which clearly breaks the very intent to make the API self documenting. Taking Wikipedia example [1], how can a client know whether the application stopped supporting withdrawals altogether (it is dynamic after all) or is it the particular account it is querying? What happens when account is overdrawn between a client querying state and attempting a withdraw? When should a client stop expecting returned endpoint to be still available? How do you document possible outcomes? Another example of HATEOAS not being thought through is the self link. If a client is querying application through proxy (e.g. forwarded port to directly unreachable destination or some kind of aggregator application), the self link becomes incorrect. Should a client know to magically rewrite the link or treat it as a redirection? If the application is reachable by various paths (domain names, IPs) it must know the path client took, to return correct self link even without a proxy. HATEOAS restricts application to a set of very specific use cases with subtle traps to fall into. I see no way to avoid both these traps and need for documentation, which, in my view, defeats the purpose. Your mileage may of course vary. [1]: https://en.wikipedia.org/wiki/HATEOAS https://en.wikipedia.org/wiki/HATEOAS