HATEOAS (Hypermedia as the Engine of Application State) is a constraint of the REST application architecture that keeps the RESTful style architecture unique from most other network application architectures. The term “hypermedia” refers to any content that contains links to other forms of media such as images, movies, and text.
This architectural style lets you use hypermedia links in the response contents so that the client can dynamically navigate to the appropriate resource by traversing the hypermedia links. This is conceptually the same as a web user navigating through web pages by clicking the appropriate hyperlinks in order to achieve a final goal.
For example, below given JSON response may be from an API like HTTP GET http://api.domain.com/management/departments/10
{ "departmentId": 10, "departmentName": "Administration", "locationId": 1700, "managerId": 200, "links": [ { "href": "10/employees", "rel": "employees", "type" : "GET" } ] }
In the preceding example, the response returned by the server contains hypermedia links to employee resources 10/employees
, which can be traversed by the client to read employees belonging to the department.
The advantage of the above approach is that hypermedia links returned from the server drive the application’s state and not the other way around.
There is no universally accepted format for representing links between two resources in JSON. You may choose to adopt the above format or you may choose to send links in HTTP response headers.
HTTP/1.1 200 OK ... Link: <10/employees>; rel="employees"
Both are absolutely valid solutions.
HATEOAS Implementation
In the real world, when you visit a website – you hit its homepage. It presents some snapshots and links to other sections of websites. You click on them and then you get more information along with more related links which are relevant to the context.
Similar to a human’s interaction with a website, a REST client hits an initial API URI and uses the server-provided links to dynamically discover available actions and access the resources it needs. The client need not have prior knowledge of the service or the different steps involved in a workflow. Additionally, the clients no longer have to hard code the URI structures for different resources. This allows the server to make URI changes as the API evolves without breaking the clients.
Above API interaction is possible using HATEOAS only.
Each REST framework provides it’s own way on creating the HATEOAS links using framework capabilities e.g. in this RESTEasy HATEOAS tutorial, links are part of resource model classes which is transferred as resource state to the client.
HATEOAS References
The following are the two popular formats for specifying JSON REST API hypermedia links:
RFC 5988 (web linking)
RFC 5988 puts forward a framework for building links that defines the relation between resources on the web. Each link in RFC 5988 contains the following properties:
Target URI: Each link should contain a target Internationalized Resource Identifiers (IRIs). This is represented by the href
attribute.
Link relation type: The link relation type describes how the current context (source) is related to the target resource. This is represented by the rel
attribute.
Attributes for target IRI: The attributes for a link include hreflang
, media
, title
, and type
, and any extension link parameters.
JSON Hypermedia API Language (HAL)
JSON HAL is a promising proposal that sets the conventions for expressing hypermedia controls, such as links, with JSON or XML. It is in the draft stage at this time.
The two associated MIME types are
media type: application/hal+xml media type: application/hal+json
Each link in HAL may contain the following properties:
Target URI: It indicates the target resource URI. This is represented by the href
attribute.
Link relation: The link relation type describes how the current context is related to the target resource. This is represented by the rel
attribute.
Type: This indicates the expected resource media type. This is represented by the type
attribute.
There is no right or wrong in choosing a hypermedia link format for your application. You should pick up a format that meets most of your use case requirements and stick to it.
James smyth says
What is really missing from this is an example of what the response to either of the following is normally presented..
HTTP GET http://api.domain.com/management/departments
ie. how to communicate that there are 1,2,3 .., 10,. departments,
or the response to
HTTP GET http://api.domain.com/management/departments/10/employees
ie. how to offer the list of employees in dept 10.
Ashish says
Hi,
I still don’t understand the purpose of the links as those are just for information and we can always configure swagger integration to provide a proper information about API.
Can someone please let me know one good reason to put these links with the restful response?
Thanks
Admin says
Links in REST helps in similar way as they help in HTML. In REST, hateoas links are for “dynamically” discovering the action and resources WITHOUT manual interaction.
Saiteja says
Basically api Connect needs rest api with static back end but ,here including some dynamic rest apis then how can i access those dynamic uri please i need help on this.
Saiteja says
hii may i know how we configure this service with api connect
please help me
Rodney Barbati says
I’m not sure about the validity of even including a POST in a link – links should be used generally for navigating to a context. A POST would be used to update the server instance of the current context, a PUT would be used to create a new instance of the current context, a DELETE would be used to delete the current context.
But if you had to include a POST in a link, and you wanted to pass parameters with it, it would be as part of the href value. Also, since the URI’s themselves are generated by the server, any parameters you might need should also be generated by the server – it knows the context when it is generating them, so it should be relatively straightforward to include them.
There is a slight disconnect with this spec and the example provided – doing a GET http://api.domain.com/management/departments would not typically return a department as shown (department 10). Rather, it would typically return a list of department ids. Calling GET http://api.domain.com/management/departments/10 would typically be expected to return the object detail for the passed id as shown above.
The examples above actually already show included parameters in the URI – do you notice where it says “href: 10/signatures” – both the 10 and the string signatures are parameters – 10 is the context id, and signatures is the entity we are interested in – this would return a list of signature id’s for department 10.
Admin says
1) POST APIs in HATEOAS links are usually on need basis. For example, if I want to provide a URL where somebody can upload an excel with all new departments information, I will include this API details with HTTP method information – because
GET
,PUT
or any other methods are not valid in this context.But in general practice, yes – you are right.
2) You are right about
/departments
API. It was a typo and has been corrected. Thanks for noticing and reporting it.Bubeeba says
In the links, the href value should either be absolute or relative to the current request uri. Given the example above, the request uri is:
http://api.domain.com/management/departments/10
Therefore the href value for linking to employees should be either of the following:
/employees
http://api.domain.com/management/departments/10/employees
The example gives the link as 10/employees which would result in the href value being incorrect as shown below:
http://api.domain.com/management/departments/10/10/employees
ich says
Your wording was a littlebit wrong:
– PUT is for UPDATE an entity in a Restful architecture
– POST for INSERT a new entity in a Restful architecture
But POST can be used for other opererations too, if there is no equivalent method is available or implementable (for unknown reason).
Henry says
Different teams/organizations implement HTTP verbs in their own fashion and that’s fine, but at least according to the HTTP Specification, the PUT should act as what we commonly refer to as an “UPSERT” – If a resources is found, modify it, else create it:
PUT
– If an existing resource is found, then the present request should be viewed as an attempt to UPDATE the existing resource with the resource state representation being provided. (I guess we might be able to debate between whether we should fully destroy the existing resource, and fully replace it with the values being provided – or simply update the existing with those values provided by the user agent in the request. But, that discussion can wait for another day…)
– However, if no resource is found, and the resource properties provided allow for the creation of the resource at that URI, then it should be CREATED – AND – a 201 (Created) MUST be returned to the user agent (rule according to SPEC).
POST
Simply said, like PUTS, POSTS can be either UPDATES or CREATES. The main difference with the POST is that the resource is subordinate to the URI and fully defined in the payload, whereas in the PUT, the resource ID is part of the URI itself – meaning you are specifically referring to “resource x” in a PUT.
Example – PUT /questions/10 – Specifically updating or creating question 10.
However, with our POST, some creation flexibility exists allowing you to create your resource and pass back a resource ID value SHOULD YOU CHOOSE TO DO SO – along with a 201 (Created).
Example – POST /questions
Here, the user agent payload allows us to create or update a question, based upon the data provided and the chosen server implementation. We are free to create the question ID of 15000, should that be the next available question ID. However, if an ID is provided, the context of the POST would likely be interpreted as an update. However, the HTTP SPEC allows us to determine those implementation rules/details in the case of a POST.
Finally (at least for this post) there is idempotency… A PUT is idempotent, while a POST is not idempotent. Meaning, you can send the same payload to the same resource and the same effect would occur, the creation of that object will happen only on the first “go-round”, and you can update it 1000 times and it will only update exactly that resource, using the exact same values. So, no additional modifications will occur.
Example Run 1000 times – PUT /questions/10
SHALL at the most create the resource once, and modify question 10 on subsequent processing attempts, using the exact same values. So no change to the resource will occur after the first time this request is processed.
Example Run 1000 times – POST /questions
Using the user agent’s defined payload and depending upon the server’s implementation:
1. This request may create 1000 questions (NOT idempotent).
2. It may take the data provided by the user agent and append it to an ID within the payload (NOT idempotent).
3. Any number of other valid options provided by the server implementation.
CONCLUSION:
Both PUT and POST are used for resource UPDATING as well as resource INSERTION.
A PUT MUST return a 201 (Created) when a new resource is created.
A POST SHOULD return a 201 (Created) when a new resource is created and a Location Header that refers to the new resource.
A PUT’s new resource location IS defined within the URI.
A POST’s new resource location is NOT defined by the URI.
A PUT is idempotent.
A POST is NOT idempotent.
So, this is more that I initially wanted to write, but, I hope it helps more than confuses. For more information, see the HTTP Spec, not another article written with bias, by me, or anyone else – it’s pretty easy to read: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
Hector Jaumandreu says
Hi
Thank you for this very useful article.
I’m trying to define an API that guides a Client through a process. In this process after getting a Resource this resource will include a Link indicating the following element that is necessary to create in the process. The plan is add a link like in your example:
But I can’t understand how to indicate the parameters for the POST. Where in the link statement should go?
Thanks for your help.
Admin says
It’s good question. I will suggest you to add a link to xsd/schema document which will define the structure of model attributes. e.g.
Now client can read the XSD document to find out about model.
====================
Another option can be that design your APIs in such a way that when a resource URL ends with “.xsd” then rather than processing the request, return the model XSD/schema document. In this way, when client want to POST on
10/signatures
, it may get the request schema byGET 10/signatures.xsd
request or something like this.Sovello says
So useful! Have been struggling to understand HATEOAS from an ‘almost-layman-perspective’ and you did it.
Pavan says
Instead of xsd schema document why can we just point to swagger file?