Quel est le problème avec HATEOAS du côté client?


35

Si je comprends bien, HATEOAS consiste essentiellement à envoyer avec chaque réponse des liens contenant des informations sur la prochaine étape. Un exemple simple se trouve facilement sur Internet: un système bancaire associé à une ressource de compte. L'exemple montre cette réponse après une requête GET à une ressource de compte

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>

Avec les données, des liens indiquent ce qui peut être fait ensuite. Si le solde est négatif, nous avons

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>

Pour que nous ne puissions que déposer. Tout va bien, si nous utilisons Fiddler ou si nous effectuons des requêtes avec le navigateur, nous pouvons facilement voir ce qui peut être fait. Ce type d’information nous est utile pour découvrir les capacités de l’API et le serveur est découplé du client.

Le problème, toutefois, est que lorsque nous construisons un client, comme un SPA avec Javascript, une application Android ou bien d’autres choses, je ne vois pas en quoi HATEOAS continue d’être pertinent. Ce que je veux dire, c’est ce qui suit: lorsque je code le SPA en javascript, je dois savoir ce qui peut être fait dans l’API pour écrire le code.

J'ai donc besoin de connaître les ressources, les méthodes prises en charge, ce qu'ils s'attendent de recevoir et ce qu'ils rendent pour pouvoir écrire les appels ajax sur le serveur et même pour construire l'interface utilisateur. Lorsque je construis l'interface utilisateur, je dois savoir qu'après avoir demandé le compte, on peut par exemple y déposer, sinon je ne pourrai pas fournir cette option sur l'interface utilisateur. De plus, je devrai connaître l'URI pour effectuer le dépôt afin de construire l'appel ajax.

Ce que je veux dire, c’est que, lorsque nous faisons des demandes à l’API, les liens nous permettent de mieux les découvrir et de les utiliser, mais lorsque nous construisons un client, l’application que nous construisons ne se contente pas de regarder les liens, puis de se rendre la bonne interface utilisateur et faire les bons appels ajax.

Alors, en quoi HATEOAS est-il important pour les clients? Pourquoi nous ennuyons-nous avec HATEOAS de toute façon?


1
Vous avez raison, mais ce n'est pas la question. HATEOAS vous évite de devoir construire les URI pour les liens dans la page sur le client.
James McLeod

Réponses:


24

l'application que nous construisons ne se contente pas de regarder les liens, puis de restituer l'interface utilisateur correcte et d'effectuer les appels ajax appropriés

En fait, c'est exactement ce que HATEOAS va donner l'interface utilisateur. Pas ce qui est possible, mais quand c'est possible. Un HATEOAS formel comme HAL , comme le dit la question, fournit des liens qui indiquent ce qui est possible. Mais lorsque ces liens apparaissent, cela dépend de l'état de l'application. Ainsi, les liens peuvent changer sur la ressource avec le temps (en fonction des actions déjà effectuées).

Cela nous permet de construire une interface utilisateur contenant tous les états possibles , sans vous préoccuper du moment où ces états deviennent actifs. Par exemple, la présence de la rel="deposit"peut indiquer directement à l’UI que le rendu du make depositformulaire est correct . Ce qui permet ensuite à l'utilisateur d'entrer une valeur et de soumettre en utilisant le lien.


2
Ainsi, lors de la construction de l'interface utilisateur, nous avons encore besoin de savoir tout ce que propose l'API. Ensuite, en regardant ces liens, nous sommes en mesure de connaître l'état des informations sur le serveur. Ainsi, par exemple, l’interface utilisateur sait qu’il est possible de déposer, de retirer, de transférer ou de fermer (connaît les noms possibles), puis elle vérifie ce qui est revenu afin de voir l’Etat?
user1620696

1
Oui, ça pourrait. Encore une fois, cela dépend de la dynamique avec laquelle vous voulez le prendre. Comme d'autres l'ont mentionné, la possibilité de modifier les liens sur le serveur (et non de casser les clients) constitue un autre avantage. Et cela devient très intéressant une fois que votre API a un iPhone, Android, Windows Phone, le Web mobile et les clients Web qui l’utilisent (sans mentionner si votre API est publiée pour que les autres puissent créer des clients).
Davin Tryon

@ user1620696 Vous devez savoir tout cela de toute façon, le client et le serveur minimisant le type de contenu, le cas échéant. Le type de contenu est beaucoup plus que dumb xml ou json. Vous devez avoir un type de contenu "dépôt bancaire" avec lequel le client comprend comment travailler
Cormac Mulhall

1
@Nik regarde HAL pour un exemple de la façon dont les liens sont fournis dans la réponse.
Davin Tryon

1
oui, vous avez toujours des problèmes de compatibilité avec les versions antérieures. Cela peut être résolu en incluant un en-tête ou une version dans l'URL. Mais, je dirais que vous comprenez correctement.
Davin Tryon

3

Si je comprends bien, HATEOAS consiste essentiellement à envoyer avec chaque réponse des liens contenant des informations sur ce qu'il faut faire ensuite.

HATEOAS est beaucoup plus que de simples liens. C'est "hyper media" en tant que moteur de l'état de l'application.

Ce qui manque dans votre description, c'est le type de contenu, la définition formelle de l'hyper media passé entre le client et le serveur.

Le HTML est un exemple d'hyper media et un exemple de la raison pour laquelle HATEOS fonctionne. La page HTML elle-même est le moteur qui permet au client (c.-à-d. L'utilisateur) de se déplacer sur le site. Un navigateur avec juste la possibilité de rendre HTML présente à l'utilisateur un site Web entièrement navigable. Ce n'est pas simplement qu'il passe des liens vers les autres pages, mais il les transmet d'une manière significative qui donne un contexte aux liens et d'une manière qui permette au navigateur de créer un site navigable.

Et plus important encore, le navigateur peut le faire avec une compréhension ZERO immédiate du site Web lui-même. Le navigateur ne connaît que HTTP et HTML. Sur la base de cette compréhension simple, il peut présenter le New York Times à l'utilisateur.

Ceci est valable même si "l'utilisateur" est un autre programme informatique. L'hyper media lui-même devrait définir le contexte de la navigation.


1
Cela ne signifie-t-il pas que vous devez créer un client aussi complexe (et sujet aux bogues) qu'un navigateur? La complexité vient souvent avec la complexité comme coût ...
Andres F.

@AndresF. cela ne signifie pas que vous devez ou devriez le faire, il vous donne simplement la possibilité de le faire dynamiquement si vous voulez ou avez besoin.
Peteris

2
@nik Bien sûr. Imaginez bien que vous ayez un service fournissant des informations sur vos ancêtres via une api reposante. Vous avez un type de contenu qui définit le format d'une ressource 'Personne' qui contient diverses informations, mais définit également le type de relation, par exemple, 'frère', 'soeur' ou 'mère', etc. Parce qu'il s'agit d'hypermédia, ces relations sont simplement avoir un URI vers une autre personne. Un client assez simple utilisant les verbes HTTP et comprenant ce type de contenu 'Personne' peut naviguer à travers cette API. Supposons que vous souhaitiez retrouver tous les descendants directs d'une personne en particulier.
Cormac Mulhall le

2
@nik Ce client doit comprendre simplement le type de contenu de la ressource à laquelle il a accédé et les verbes HTTP (GET, PUT, DELETE, etc.) et vous pouvez naviguer à travers cette API pour extraire et mettre à jour des ressources. Et, plus important encore, tout client qui comprend le type de contenu peut basculer entièrement, via un URI, vers un autre serveur et continuer en l'état. Ils se soucient peu de savoir à quel serveur ils parlent, ils ne se soucient que du type de contenu de la ressource, le comprennent-ils ou non.
Cormac Mulhall le

1
@Nik Donc, dans une telle situation, vous avez un serveur qui comprend le type de contenu d'origine (par exemple, Personne v1) et le nouveau type de contenu (Personne v2). Le client ne comprend que Person v1. Le client indique au serveur quels types de contenu il comprend via l’en-tête Accept de HTTP. À l'aide de la négociation de contenu, le serveur détermine s'il enverra ce que le client prend en charge. Dans ce cas, il renverra la ressource à l'aide du type de contenu Person v1. Maintenant, vous voudrez peut-être simplement cesser de prendre en charge cet ancien type de contenu et envoyer une erreur 406 au client. Il est préférable d’essayer de soutenir autant que possible.
Cormac Mulhall

2

Vous n'avez pas à créer une interface générée dynamiquement. Bien que cela puisse être agréable, ce n'est pas nécessaire. Si vous ne pouvez pas construire une interface dynamique, utilisez simplement les liens et vous avez terminé. L’inconvénient est que vous êtes à nouveau fortement lié au serveur et que vous allez tomber en panne si quelque chose change.

Utiliser la mise en page dynamique peut être assez simple d'ailleurs:

links.forEach(function(link) {

  switch(link.rel) {

    case 'deposit':
      showDepositButton();
      break;

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

});

Il vous enregistre dans votre code client comme:

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

Vous pouvez mettre en place une position négative autorisée (en empruntant de l'argent par exemple) sans changer de client.


Par exemple, la banque peut proposer des limites de découvert variables sur ses comptes, sans avoir à dire au client quelle est la limite applicable à chaque compte.
Bart van Ingen Schenau

Correct, vous pouvez décider des limites d’équilibre aussi complexes que vous le souhaitez sans avoir à modifier le client. Si vous allez plus loin avec les parties REST telles que le type de contenu, vous pouvez afficher différentes vues. Par exemple, un compte semble différent d'une transaction. Le code à la demande (bien que peu implémenté) est également intéressant. Cela pourrait être utilisé par exemple pour un estimateur emprunteur. Il peut donner à l'interface une fonction de calcul simple, de sorte que le client n'a besoin que d'implémenter les entrées pour le calcul. Il restera à jour à partir du back-end.
Luc Franken

2
Mais généralement, le client doit savoir POURQUOI il ne peut pas se retirer. Nous devons donc toujours envoyer au client un ENUM ou une chaîne dans un champ séparé reason. Et si nous en avons toujours besoin, pourquoi ne pas simplement lui envoyer un autre champ booléen canWithdrawau lieu d’un lien vers l’action? Un autre avantage est la possibilité de modifier l'URL d'une action sans toucher le client. Mais .. quelle raison de changer l'URL? Dans la plupart des cas, certains changements de sémantique, de paramètres ou de forme de requête / réponse, etc., sont également nécessaires. Nous devons donc modifier le client. Donc, je ne comprends toujours pas - quel est le but d'HATEOAS.
Ruslan Stelmachenko
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.