HATEOAS And HAL – And Why You Should Use It For Your REST API

Let’s face it, we all love REST. As data models grow and functionality increases, REST APIs can quickly become complex.

For the design and documentation of an API, I use Swagger.

In the screenshot, you can see an example API as shown by the Swagger UI.

There is no logical link between individual resources.

 

HATEOAS/HAL extends REST by the possibility to guide a user/client through.

HATEOAS is a concept of application architecture. It defines the way in which a clients application interact with the server, by navigating hypermedia links they find inside resource models returned by the server.

Since HATEOAS is only a concept, we need some standard to describe the resources, that contain hypermedia information (links to related resources).
HAL is one of such standards. It is a specific format of resource presentation, that can be used to implement HATEOAS.

For example, an answer without HATEOAS might look like this:

{
  "id": 1,
  "city:" "Vienna"
}

A client without knowledge of the possibilities of the API does not know now that he may change or delete the entry.

Let’s assume you want to tell the client that it can edit and delete this entry. With REST this is not possible.

Let’s look at the same example with implementing HATEOAS using HAL to describe the links:

URI: http://localhost:8080/api/v1/cities/1

{
  "id": 1,
  "city": "Vienna",
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/v1/cities/1"
   }
 }
}

The first link assigned to a resource is called a self-link. It is the self-relationship – the canonical place where the resource is accessible.

This link is of course not very helpful. Let’s have a look at a more complex example: a client should change the entry “Vienna” and confirm afterwards.

The first case is simple, and CRUD provides us with the operation PUT, which usually refers to the self-link. However, how do we determine the confirmation link?
We use an additional link which we label with the label “accept”.

The client that implements the API has to check in the list of links if there is a function “accept” and follow the link.

URI: http://localhost:8080/api/v1/cities/1

{
  "id": 1,
  "city": "Vienna",
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/v1/cities/1"
    },
    "accept": {
      "href": "http://localhost:8080/api/v1/cities/1"
    }
  }
}