Hypermedia as the Engine of Application State (HATEOAS)

Overview

Think of HTML tags like hyperlinks, img and forms which are all called hypermedia controls. These controls will be a part of HTML document (otherwise primary resource). While making a request to this primary resource, all the associated links will be returned in the response document where client shall navigate to those whenever required.
Below is the example for anchor tag.
1 <a href="http://www.example.com/messages/">some text here</a>

If you think of the functionality of this control, it makes a HTTP GET request to the URL specified in the href attribute. Resource associated with this request will be returned back and rendered in the browser.

Similarly with form control,
1
2
3
4
<form action="http://www.example.com/messages" method="post">   
<input type="text" name="message" value="" required="true" />   
<input type="submit" value="Post" />
</form>
on clicking the submit button, browser makes a HTTP request with the URL mentioned in the action attribute and type of request will be determined based on the value specified in method attribute. If it is POST request, request body is constructed with the value provided in the form fields.

Basically HTTP request will require these four things. URl, Method, Headers, Entity Body. Hypermedia controls provides the client these capabilities to specify while making the request.

Similarly in the same way, hypermedia APIs work. When client request for the primary resource, server sends the links whichever makes more sense to the client as the next requests along with the primary resource response representation.

Hypermedia API is the strategy and not a technology. Based on the strategy, there are plenty of technology being developed. E.g. Collection+JSON, Siren, HAL, JSON API etc.

From Client Perspective

There will be many URLs provided by the server, those will be hard coded at the client application. Client has to keep track of all URLs, respective HTTP methods, media types and entity bodies that needs to be posted.

This is a more tightly coupled way of building an application. Any changes, the server plans to make needs to be more careful on not affecting the client. But that's not going to be the case always. Business is ever changing, server will do the breaking changes that might affect the URL format or request entity body. With just REST API, this is unavoidable and client has to make the respective changes in their code.

One way to limit this problem is through hypermedia. Hypermedia reduces the number of URLs being hard coded at the client. It connects each resources using links. Using Hypermedia, the server tells the client to which URL it has to make the next request in the future. Server bundles all the related links in the response representation of the primary request.

This is how even the client hypermedia controls work. E.g. HTML <a> tag, its href attribute provides the URL, and its default method is GET and browser adds the respective media type while making the request. These kind of capabilities need to provide on supporting hypermedia at API level too.

Design Approach

Author of the book Restful Web APIs says, thinking on the API design based on identifying resources and grouping them together using hypermedia is a one way of designing APIs. This approach is called resource-oriented approach. Resource-oriented approach is one good way to connect related resources.
But in hypermedia-based approach, resources needs to be connected based on the state transitions. It comes with better understanding of the consumers.
Hypermedia can also be stated as a runtime intellisense for REST APIs. Whole purpose is to reduce coupling between client and server. This is especially important, if you have more than one client for your APIs.

URL Design doesn't matter

Highlighting below a statement from the book, The Architecture of World Wide Web, Volume One.
It is tempting to guess the nature of a resource by inspection of a URI that identifies it. However, the Web is designed so that agents communicate resource information state through representations, not identifiers. In general, one cannot determine the type of a resource representation by inspecting a URI for that resource.
To explain the above statement, consider we have a URL /users that return a collection of users. To fetch a single user information, it takes the format of /users/john. This URL will return information about user John. But the question is, what do you think this URL is representing. Can you able to identify the resource based on the URL format or identifier. If you would have thought that this URL would have returned user information, like demographics then you are wrong. Same kind of URL pattern shall return user configuration as the representation. It is not the URL that identifies the resource, but it is the representation.

Representer Pattern

Way of supporting API in more than one format. It depends on the requirement from the client. Request from the client will have a Accept header, in the format he needs the response representation.

But do we really need to support multiple formats? Most of the time, client-server will have an agreement on supporting strong typing in the message being passed between them. Whatever the format it is, both expects deserializing the message will get them a required object.

Representer pattern might needs to be followed if the client implements a dynamic ui based on the format of one the hypermedia format. If so adding adding new attribute at the API, will not affect the client code. Need more exploration on this bit.

Recommendations

  1. Don't take things away - removing an existing elements from your api forces your client to make chages in their or left behind with the older version. If you want your client to travel along with your development, do not break the promise.
  2. Don't change the meaning of things - in hypermedia, client work based on your terminology provided on your response representation. Say you have a relationship link in the name of users that provides list of all users. Client builds the UI based on this promise. Later if you change the response of this relation to return only active users, meaning of relation will be changed that will affect the client.
  3. Make new things as optional - also related to avoiding breaking changes.
  4. Code defensively - Doing defensive coding at client will also avoid breaking changes. In this case, your code will not be affected by the new attributes added the api. This has been made possible by adopting to hypermedia format. Without it, each api will be exposing its respective schema that will be maintained at the client as well. By adopting to hypermedia format, data format will not change though the server makes changes to the internal object model.
  5. Document link identifiers, not URLs - one important thing in using hypermedia. From server perspective, do not document the static URLs. URLs are prone to change. Client should not depend on the hardcoded URLs at their end. Instead document, identifiers of those endpoints. Like enabledModules, issueCourse etc.
  6. Support dynamic resources - providing related links must be dynamic based on the workflow and even based on the requesting user access. It is not supposed to return all the related links always as part of response representation. Only the appropriate links must be returned in the response.

Examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"links": [{
"href": "https://api.paypal.com/v1/payments/sale/36C38912MN9658832",
"rel": "self",
"method": "GET"
}, {
"href": "https://api.paypal.com/v1/payments/sale/36C38912MN9658832/refund",
"rel": "refund",
"method": "POST"
}, {
"href": "https://api.paypal.com/v1/payments/payment/PAY-5YK922393D847794YKER7MUI",
"rel": "parent_payment",
"method": "GET"
}]
}

Downside

  • API implementation can become complex.
  • No guarantee that client is going to follow guideline provided by API. If all related resources APIs are published publicly, then more chances for the client to directly access the resources rather than following state transition style of navigation.

Good Reads

Comments