web-dev-qa-db-fra.com

Qu'est-ce que HATEOAS offre pour la découvrabilité et le découplage en plus de la possibilité de changer votre structure URL plus ou moins librement?

Dernièrement, j'ai lu sur Hypermedia en tant que moteur d'état de l'application (HATEOAS), la contrainte qui est censée rendre une API Web "vraiment RESTful". Cela revient à inclure essentiellement des liens avec chaque réponse aux transitions possibles que vous pouvez effectuer à partir de l'état actuel.

Permettez-moi d'illustrer ce que HATEOAS est basé sur ma compréhension - et veuillez me corriger si j'ai raté quelque chose.

/
    GET: {
        "_links": {
            "child": [
                { "href": "http://myapi.com/articles", "title": "articles" }
            ]
        }
    }

/articles?contains=HATEOAS
    GET: {
        "_items": [
            { "uri": "http://myapi.com/articles/0", "title": "Why Should I Care About HATEOAS?" },
            { "uri": "http://myapi.com/articles/1", "title": "HATEOAS: Problem or Solution?" }
        ],
        "_links": {
            "self": { "href": "http://myapi.com/articles", "title": "articles" },
            "parent": { "href": "http://myapi.com/", "title": "home" }
        }
    }

    POST: {
        "title": "A New Article",
        "body": "Article body",
        "tags": [ "tag1", "tag2" ]
    }

/articles/0
    GET: {
        "title": "Why Should I Care About HATEOAS?",
        "body": "Blah blah blah"
        "tags": [ "REST", "HATEOAS" ],
        "_links": {
            "self": { "href": "http://myapi.com/articles/0", "title": "article" },
            "parent": { "href": "http://myapi.com/articles", "title": "articles" }
        }
    }

HATEOAS aurait deux avantages majeurs:

  1. L'ensemble du service est détectable à partir de l'URI racine, la documentation n'est plus nécessaire.

  2. Le client est découplé du serveur qui peut désormais modifier librement la structure de l'URI. Cela élimine le besoin de versionner l'API.

Mais à mon avis, un service est bien plus que sa structure d'URI. Pour l'utiliser efficacement, vous devez également connaître:

  • quels paramètres de requête vous pouvez utiliser et leurs valeurs possibles
  • la structure du JSON/XML/quels que soient les documents dont vous avez besoin pour envoyer vos requêtes POST/PATCH/etc
  • la structure de la réponse envoyée par le serveur
  • les erreurs possibles qui pourraient survenir
  • ...

Sur la base de ce qui précède, HATEOAS ne résout qu'une infime partie des problèmes de découverte et de couplage. Vous devez toujours documenter les quatre aspects ci-dessus et les clients seront toujours fortement couplés au serveur à cause d'eux. Pour éviter de casser des clients, vous devez toujours mettre à jour votre API.

Le seul avantage qu'il offre est que vous pouvez modifier votre structure URL plus ou moins librement (au fait, qu'est-il arrivé au principe "Les URI cool ne changent pas" ?). Ma compréhension est-elle correcte?

63
Botond Balázs

Je pense que vos instincts sont largement corrects; ces avantages proclamés ne sont vraiment pas si grands, car pour toute application Web non triviale, les clients devront se soucier de la sémantique de ce qu'ils font ainsi que de la syntaxe.

Mais cela ne signifie pas que vous ne devez pas faire en sorte que votre candidature suive les principes de HATEOAS!

Que signifie HATEOAS vraiment? Cela signifie structurer votre application pour qu'elle soit en principe comme un site web , et que toutes les opérations que vous souhaitez effectuer peuvent être découvertes sans avoir à télécharger un schéma complexe. (Les schémas WSDL sophistiqués peuvent tout couvrir, mais au moment où ils le font, ils ont dépassé la capacité de pratiquement tous les programmeurs à comprendre, sans parler d'écrire! Vous pouvez voir HATEOAS comme une réaction contre une telle complexité.)

HATEOAS ne signifie pas seulement des liens riches. Cela signifie en utilisant les mécanismes d'erreur de la norme HTTP pour indiquer plus exactement ce qui a mal tourné; vous ne devez pas simplement répondre par "waaah! non "et peut à la place fournir un document décrivant ce qui s'est réellement passé et ce que le client pourrait faire à ce sujet. Cela signifie également prendre en charge des choses comme requêtes OPTIONS (la manière standard de permettre aux clients de découvrir quelles méthodes HTTP ils peuvent utiliser) et négociation du type de contenu afin que le format de la réponse puisse être adapté à un formulaire que les clients peuvent gérer. Cela signifie mettre un texte explicatif (ou, plus probablement, des liens vers celui-ci) afin que les clients puissent voir comment utiliser le système dans des cas non triviaux s'ils ne savent pas; le texte explicatif peut être lisible par l'homme ou il peut être lisible par une machine (et peut être aussi complexe que vous le souhaitez). Enfin, cela signifie que les clients ne synthétisent pas les liens (sauf pour les paramètres de requête); les clients n'utiliseront un lien que si vous le leur avez dit.

Vous devez penser à faire parcourir le site par un utilisateur (qui peut lire JSON ou XML au lieu de HTML, donc un peu bizarre) avec une mémoire super pour les liens et une connaissance encyclopédique du HTTP normes, mais sinon aucune connaissance de ce qu'il faut faire.

Et bien sûr, vous pouvez utiliser la négociation de type de contenu pour servir un client HTML (5)/JS qui leur permettra d'utiliser votre application, si c'est ce que leur navigateur est prêt à accepter. Après tout, si votre API RESTful est bonne, cela devrait être "trivial" à implémenter par dessus?

49
Donal Fellows

Le fait est que HATEOAS doit venir avec un deuxième pilier qui définit ce qu'est une API RESTful: le type de média standardisé. Roy se disant lui-même

Une API REST devrait consacrer presque tout son effort descriptif à définir le ou les types de supports utilisés pour représenter les ressources ".

Avec un type de média standardisé qui définit la transition de manière explicite et un hypertexte pour pointer les ressources les unes vers les autres, vous pouvez créer un graphe de ressources qui peut prendre n'importe quelle forme sans casser aucun client. Comme le travail sur le Web, vraiment: vous avez un lien entre le document et le document est écrit en HTML qui définit comment suivre ces liens. <a href> est un GET, <form> est GET ou POST (et définissez le modèle d'URL à utiliser en cas de GET), <link type="text/css"> est GET ... etc. C'est ainsi que les navigateurs peuvent naviguer sur une page HTML structurée arbitrairement et sur le Web.

Tout ce que vous avez dit

  • quels paramètres de requête vous pouvez utiliser et leurs valeurs possibles
  • la structure du JSON/XML/quels que soient les documents dont vous avez besoin pour envoyer vos requêtes POST/PATCH/etc
  • la structure de la réponse envoyée par le serveur
  • les erreurs possibles qui pourraient survenir

Sont des points qui devraient être adressés par la définition de votre type de média standardisé . Bien sûr, c'est beaucoup plus difficile, et ce n'est pas quelque chose auquel la plupart des gens pensent lorsqu'ils définissent une API "REST". Vous ne pouvez pas simplement prendre vos entités commerciales et insérer leurs attributs dans un document JSON pour avoir une API RESTful.

Bien sûr, ce qui s'est passé est REST s'est en quelque sorte dilué pour signifier "utiliser HTTP au lieu de compliqué SOAPy". Il ne suffit pas d'utiliser HTTP et HyperText pour être RESTful, c'est ce que la plupart des gens se trompent .

Non pas que cela soit nécessaire et une mauvaise chose: REST sacrifiez les performances et la facilité de développement en échange d'une maintenabilité et d'une évolutivité à plus long terme. Il a été conçu pour l'intégration d'applications de grande entreprise. la structure JSON codée en dur peut être ce dont vous avez besoin. N'appelez pas cela REST, c'est une API web ad-hoc, rien de plus. Et cela ne veut pas dire que c'est nul, cela signifie simplement qu'il n'essaie pas de suivre le contrainte de REST.

Lectures complémentaires

J'espère que cette aide clarifiera un peu :)

6

Il existe certains formats Hypermedia qui s'efforcent de fournir des réponses plus riches qui incluent plus d'informations sur le type de demandes à envoyer, et rien ne vous empêche d'enrichir la réponse avec encore plus d'informations.

Voici un exemple Siren document:

{
  "class": [ "order" ],
  "properties": { 
      "orderNumber": 42, 
      "itemCount": 3,
      "status": "pending"
  },
  "entities": [
    {
      "class": [ "info", "customer" ],
      "rel": [ "http://x.io/rels/customer" ], 
      "properties": { 
        "customerId": "pj123",
        "name": "Peter Joseph"
      },
      "links": [
        { "rel": [ "self" ], "href": "http://api.x.io/customers/pj123" }
      ]
    }
  ],
  "actions": [
    {
      "name": "add-item",
      "title": "Add Item",
      "method": "POST",
      "href": "http://api.x.io/orders/42/items",
      "type": "application/x-www-form-urlencoded",
      "fields": [
        { "name": "orderNumber", "type": "hidden", "value": "42" },
        { "name": "productCode", "type": "text" },
        { "name": "quantity", "type": "number" }
      ]
    }
  ],
  "links": [
    { "rel": [ "self" ], "href": "http://api.x.io/orders/42" },
    { "rel": [ "previous" ], "href": "http://api.x.io/orders/41" },
    { "rel": [ "next" ], "href": "http://api.x.io/orders/43" }
  ]
}

Comme vous pouvez le voir, des informations sur la façon d'appeler les actions connexes sont fournies dans le message, puis en interprétant ces informations, le client devient plus résistant aux modifications.

Il devient particulièrement puissant si les rel sont des URI qui peuvent être recherchés, plutôt qu'à partir d'un vocabulaire fixe.

2
mcintyre321

(HATEOAS), la contrainte qui prétend rendre une API web "vraiment RESTful"

La seule chose qui en fait une véritable API REST satisfait toutes les contraintes, pas seulement une seule.

Mais à mon avis, un service est bien plus que sa structure d'URI. Pour l'utiliser efficacement, vous devez également savoir: ...

C'est pourquoi nous avons besoin des autres contraintes, du message auto-descriptif, etc ...

Pour éviter de casser des clients, vous devez toujours mettre à jour votre API.

Peu importe comment vous essayez, vous devrez mettre à jour votre API. Dans un client REST, vous devez toujours savoir comment accéder à une page où vous voulez faire des choses, quels liens suivre et quelles propriétés vous devez collecter en fonction du vocabulaire RDF décrivant le message. Si vous devez remplacer ou supprimer quelque chose de ce vocabulaire, cela cassera probablement tous vos clients et vous aurez besoin d'une nouvelle version. Je pense donc que REST n'est pas quelque chose que vous devez publier tôt (et comprendre le modèle pendant que vous changez constamment l'API), sinon vous aurez de nombreuses versions. Vous avez d'abord besoin d'un modèle de domaine stable sur lequel vous pouvez construire ...

0
inf3rno

Où avez-vous lu que "la documentation n'est plus nécessaire" pour les services HATEAOS? Comme vous le dites, vous devez toujours documenter la sémantique des liens. Cependant, avec HATEOAS, vous n'avez pas besoin de documenter, et donc de conserver pour toujours, la structure de la plupart des URI.

HATEOAS permet à un implémenteur de service de modifier et de mettre à l'échelle l'implémentation de manière significative et efficace sans changer un petit ensemble d'URI dont dépend le client. Il est plus facile de conserver un petit nombre de points d'entrée inchangé qu'un grand ensemble. Par conséquent, la réduction du nombre de points d'entrée publics vers le service et la fourniture dynamique de liens vers des sous-ressources (HATEOAS) prennent en charge les "URI cool ne changent pas" mieux que les services non HATEOAS.

0
Jonathan Giddy