HATEOAS, the scary acronym
Join the DZone community and get the full member experience.
Join For FreeHATEOAS (Hypermedia As The Engine Of Application State) is one of the most important constraints in REST. Yet some explanations of this principle found on the web are a bit nebulous; I've seen HATEOAS presented in several different sauces and in this article I list these examples and draw up a simple comparison to understand it in less than 5 minutes. Even the Wikipedia article, to use as a starting point, is surprisingly short.
On the practical side, HATEOAS is primarily about including URLs in responses so that clients may navigate towards their desired resource, instead of jumping to hardcoded URLs:
GET /users ... HTTP/1.1 200 Ok [ { name: 'giorgio', profile: '/users/giorgio' }, ... ]
The question to answer in this article is why we should do that.
Parking lots
Wayne Lee's presentation compares HATEOAS to a parking lot with a single entrance, where car drivers can be told where to go. An old style web service has instead multiple entrances, and you must manage all incoming requests to each one of these entrances (URLs). Backward compatibility becomes a chore, since you have to keep all the URLs you have ever supported.
This work is also valuable for providing convincing examples of new requirements which trump the old URLs, suggesting thay they are not meant to be a static part of the Api:
- inclusion of user parameters in the URL to replace the old session-based solution (solution... Read hack).
- New professional accounts, where data are retrieved from a different domain name corresponding to a faster server.
- VIP accounts with a custom domain name.
These neverending list of requirements shows also how the client becomes more and more complex in order to address all of the cases; in the HATEOAS case, the complexity is moved to the server, which only lists the URLs available to the current client.
Request/response examples
Alessandro Nadalin, paladin of REST in Italy, draws a simpler comparison with <link> HTML elements and an example of the 201 Created response code usage. When a resource is created with POST, you can return a Location header in your response, so that the client can follow that link to the new resource instead of dreaming up an URL which, eventually, will break:
POST /users HTTP/1.1 201 Created Location: /users/1
The HTML example deserves further space, since a web developer is more likely to be familiar with HTML and old school websites than with the HTTP specification. This may make you sad; but is a fact of life: since learning HTML has a lower barrier of entry than playing with HTTP headers, there will inevitably be more people knowing how to use the former than the latter. Let's dumb it down even more.
Those old <a> tags
For the average web developer understanding HATEOAS and many REST concepts become simpler once he grasp the following principle. This principle is related to REST as a response to SOAP and the use of HTTP as a tunnel for other protocols
The largest distributed system in the world is the web. The web is reliable and robust, it scales very well. The web is based on resources exchange, not on sending commands. When we build web services, let's copy the architectural style of the web, in order to earn its properties. The only difference is that the clients are machines instead of humans.
The misuse of POST over GET for retrieving resources maps to your browser's warning that it would have to resubmit a form once you refresh a search page. The misuse of GET for non-idempotent actions maps to deletion links realized with <a> (which everyone of us has done once in his life), promptly followed by Google's crawler.
So to which concept of the 90s web does HATEOAS map? Let's say you're building a website for your uncle's farm.
You may design a set of pages representing each type of animal your uncle has:
/animals/duck.html /animals/cow.html /animals/pig.html
Then, you have to spread the knowledge about these links, and let the users of the website know about all these fancy pages. Like every web developer worth its salt, you make up a PDF documents containing specifications for building these URIs:
/animals/%s.html #substitute the name of the animal from our list
and you send it via snail mail to each registered user.
This is crazy, right? And that's exactly what almost every webservice does (including the ones I designed myself): URL patterns are listed so that you can build the URL of a leaf resource without passing from the intermediate ones. These URL templates are published out-of-band, as documentation of the web service, in a different format.
And not implementing HATEOAS is like ditching the <a> element and expecting our users to build links themselves and put them in the browser's location bar. For sure, it's a way to break them when these formats change; but it's also a lot of work if you compare it with embedding the links to follow into the responses like every 90s website did.
HATEOAS is not a panacea, and definitely not the only thing we need to build an evolvable web service which does not break clients. Yet it's an important shift: we think about how to reach a resource while making minimal assumptions, instead of randomly typing endpoints in our location bar.
Opinions expressed by DZone contributors are their own.
Comments