35

As I currently understand HATEOAS is basically all about sending together with each response links with information about what to do next. One simple example is easily found on the internet: a banking system together with an account resource. The example shows this response after a GET request to an account resource

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">100.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
    <link rel="withdraw" href="/account/12345/withdraw" /> 
    <link rel="transfer" href="/account/12345/transfer" /> 
    <link rel="close" href="/account/12345/close" /> 
</account>

Together with the data there are links telling what can be done next. If the balance is negative we have

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">-25.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
</account>

So that we can only deposit. That's all fine, if we are using Fiddler or making requests with the browser we can easily see what can be done. This kind of information is useful then for us to discover the API's capabilities and the server is decoupled from the client.

The point, however, is that when we build a client, like a SPA with Javascript, or an Android app or many other things, I can't see how HATEOAS continues being relevant. What I mean is the following: when I'm coding the SPA in javascript, I must know what can be done in the API in order to write the code.

So I need to know the resources, the methods supported, what they expect to receive and what they give back in order to write the ajax calls to the server and even in order to build the UI. When I build the UI, I must know that after requesting the account, one can for example deposit into it, or I won't be able to provide this option on the UI. Also, I'll need to know the URI to make the deposit to build the ajax call.

What I mean is, when we make requests to the API, links do allows us to discover and use the API better, but when we build a client, the app we are building won't simply look at the links and then by itself render the correct UI and make the right ajax calls.

So, how is HATEOAS important for the clients? Why do we bother with HATEOAS anyway?

  • 1
    You're right, but that's not the point. HATEOAS keeps you from having to construct the URIs for the links in the page on the client. – James McLeod Feb 8 '15 at 23:00
24

the app we are building won't simply look at the links and then by itself render the correct UI and make the right ajax calls

In fact, this is exactly what HATEOAS will give the UI. Not what is possible, but when it is possible. A formal HATEOAS like HAL, as the question states, gives links that indicate what is possible. But when those links show up depends on the state of the application. So, the links can change on the resource over time (based on actions that have already been performed).

This allows us to build a UI that contains all the possible states, but not be concerned with when those states become active. For example, the presence of the rel="deposit" can directly tell the UI when it is OK to render the make deposit form. Which then allows the user to enter a value and submit using the link.

  • 2
    So when building the UI we still need to know everything that the API offers, and then looking at those links we are able to know the state the information on the server is at? So for instance, the UI knows it's possible to deposit, withdraw, transfer or close (knows the possible rels), then it checks what came back in order to see the state? – user1620696 Feb 9 '15 at 22:12
  • 1
    Yes, it could. Again it depends on how dynamic that you want to take it. As others have mentioned, the ability to change links on the server (and not break clients) is another advantage. And this becomes very interesting once your API has an iPhone, Android, Windows Phone, Mobile Web and Web clients that all use it (not to mention if your API is published for others to build clients on). – Davin Tryon Feb 9 '15 at 22:16
  • @user1620696 You should know all of this anyway through both the client and server understating the content type if the resoure. Content type is a lot more than dumb xml or Json. You should have some "bank deposit" content type that the client understand how to work with – Cormac Mulhall Feb 10 '15 at 13:23
  • 1
    @Nik take a look at HAL for an example of how the links are provided in the response. – Davin Tryon Jan 25 at 11:11
  • 1
    yes, you still have backwards compatibility concerns. This can be solved by including a version header or version in the url. But, I would say you are understanding correctly. – Davin Tryon Jan 25 at 11:53
3

As I currently understand HATEOAS is basically all about sending together with each response links with information about what to do next

HATEOAS is a lot more than just links. It is "hyper media" as the engine of application state.

What is missed in your description is the content type, the formal definition of the hyper media that is passed between client and server.

HTML is an example of hyper media, and an example of why HATEOS works. The HTML page itself is the engine that allows the client (ie the user) to move through the site. A browser with just an ability to render HTML present to the user a fully navigable website. It is not simply that it passes links to the other pages but it passes them in a meaningful way that gives context to the links and in a fashion that allows the browser to construct a navigable site.

And most importantly the browser can do this with ZERO up front understanding of the website itself. The browser only knows HTTP and HTML. Based on that simple understanding it can present the New York Times to the user to navigate through.

This holds even if the "user" is another computer program. The hyper media itself should define the context of navigation.

  • 1
    Wouldn't this mean that you must build a client as complex (and bug prone) as a browser? Flexibility often comes with complexity as a cost... – Andres F. Feb 9 '15 at 12:33
  • @AndresF. it doesn't mean that you must or should do so, it merely gives you the option to do it dynamically if you want or need it. – Peteris Feb 9 '15 at 15:25
  • 2
    @nik Sure. Off the top of my head imagine that you have a service providing ancestry information via restful api. You have a content type that defines the format of a 'Person' resource that has various information about them but also defines what relationships look like, say 'brother' or 'sister' or 'mother' etc. Because this is hypermedia those relationships simply have a URI to another Person resource. A fairly simple client using the HTTP verbs and understanding this 'Person' content type can navigate through this API. Say you want to find all direct descendants of a particular person. – Cormac Mulhall Feb 6 at 16:44
  • 2
    @nik This client needs to understand simply the content type of the resource it has accessed and HTTP verbs (GET, PUT, DELETE etc) and you can navigate through this API fetching and updating resources. And, more importantly, any client that understands the content type can jump, via a URI, to another server entirely and continue on as they were. They don't care what server they are talking to, they care only about the content type of the resource, do they understand it or not. – Cormac Mulhall Feb 6 at 16:48
  • 1
    @Nik So in such a situation you have a server that understands the original content type (say Person v1) and the new content type (Person v2). The client only understands Person v1. The client tells the server what content types it understands via the Accept header in HTTP. Using content negotiation the server determines if it will send what the client supports, in which case it will return the resource using content type Person v1. Now you may want to simply stop supporting this old content type and can send the client a 406 error. It is better to try and support as much as you can though. – Cormac Mulhall Feb 11 at 11:06
2

You don't have to build a dynamically generated interface. Though it could be nice it's not required. If you cannot build a dynamic interface just use the links and you are done. Disadvantage is that you are again hard linked to the backend and will crash if something changes.

Using the dynamic layout can be quite simple btw:

links.forEach(function(link) {

  switch(link.rel) {

    case 'deposit':
      showDepositButton();
      break;

    case 'withdraw':
      loadWithdrawForm(link.href);
      showWithdrawButton();
      break;
  }

});

It saves you in your client code like:

if (balance <= 0 && negativeBalanceAllowed === false) {
  showWithdrawButton();
}

You can implement an allowed negative position (by borrowing money for example) without changing your client.

  • As a slightly stronger example, the bank can offer variable overdraft limits on their accounts, without having to tell the client side what the limit is on each account. – Bart van Ingen Schenau Feb 9 '15 at 9:30
  • Correct you can make the decision of balance limits as complex as you want and still don't have to make changes to the client. If you take this further with REST parts like content type you can show different views. For example an account looks different from a transaction. Also interesting is code on demand (though not much implemented). That could be used for example for a borrowing estimator. It can give the interface a simple calculator function so the client only needs to implement the inputs for the calculation. It will stay up-to-date from the back-end. – Luc Franken Feb 9 '15 at 13:38
  • 2
    But usually the customer need to know WHY it can't withdraw, so we still need to send an ENUM or String in separate field to the client with reason. And if we still need this, why not simply send him another boolean field canWithdraw instead of a link to the action? Another advantage is ability to change an action's URL without touching the client. But.. what reason to change the URL? In most cases it also some change in semantic or parameters or request/response shape etc. So we anyway need to change the client. So, I still don't get it - what the point of HATEOAS. – Ruslan Stelmachenko Dec 17 '17 at 16:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.