Categories
Architecture Software

HATEOAS in the context of microservices

In the rise of RESTful, microservice-based architectures in our web applications, HATEOAS seems to have fallen out of favour. This is curious, given that the creator of REST specifically advocates for HATEOAS, going so far to say that REST isn’t truly REST without it. There have also been articles disparaching it as a practice, claiming that there isn’t a sensible alternative to the current practices.

So this article will re-evaluate HATEOAS’s usefulness, specifically in the context of modern microservices. I’ll quickly outline what HATEOAS is first, and then walk through a case study which will justify its usage.

What is HATEOAS

HATEOAS is a long, needlessly intimidating acronym for Hypermedia as the Engine of Application State.

Hypermedia is:

…an extension of the term hypertext, […] a nonlinear medium of information that includes graphics, audio, video, plain text and hyperlinks.

and hypertext is just text that you can view on your computer screen.

Bringing this all together, HATEOAS forms a principle that application state should be represented and — crucially — discovered by resources on the web. These resources are themselves hypermedia (e.g. web content such as JSON documents, located by URIs).

Those who interact with a RESTful API should be able to navigate through it like a text-based adventure:

$ a-text-adventure-game
  You are in an empty room with a door and an open window. What do you do?
    [1] Open door
    [2] Go to window
  > 2
  You are now at the window. What do you do?
    [1] Close window
    [2] Go back to centre of the room
  ...

Each "response" gives you the set of "valid" moves that can be made. You follow the moves and get another set of "valid" moves based on where you are currently at.

There are already clear cases where we use HATEOAS at least partially. When you want to present an image as part of your API, you give a URL to the source, rather than a binary string representation of the raw image itself. The same goes for other file types: PDFs, videos, music, etc… — hypermedia is the most versatile way we have of sharing (references to) content, so why not go further in using this?

The text-based adventure above in a RESTful API could look a bit like this:

// POST /
// Content-Type: application/vnd.atextadventuregame+json
{
    "session_id": "d62230ed-71f7-4fe2-8313-8b0f13e8c2a9"
    "message": "You are in an empty room with a door and an open window. What do you do?",
    "options": [
        {
            "id": "1",
            "label": "Close window",
            "_link": "/sessions/d62230ed-71f7-4fe2-8313-8b0f13e8c2a9/1"
        },
        {
            "id": "2",
            "label": "Go back to centre of the room",
            "_link": "/sessions/d62230ed-71f7-4fe2-8313-8b0f13e8c2a9/2"
        }
    ]
}
// POST /sessions/d62230ed-71f7-4fe2-8313-8b0f13e8c2a9/2
// Content-Type: application/vnd.atextadventuregame+json
{
    "session_id": "d62230ed-71f7-4fe2-8313-8b0f13e8c2a9"
    "message": "You are now at the window. What do you do?",
    "options": [
        {
            "id": "1",
            "label": "Open door",
            "_link": "/sessions/d62230ed-71f7-4fe2-8313-8b0f13e8c2a9/1"
        },
        {
            "id": "2",
            "label": "Go to window",
            "_link": "/sessions/d62230ed-71f7-4fe2-8313-8b0f13e8c2a9/2"
        }
    ]
}

Let’s look into a more realistic example.