89 votes

HATEOAS: URLs absolus ou relatifs?

Lors de la conception d'un service web RESTful utilisant HATEOAS, quels sont les avantages et les inconvénients de montrer un lien sous la forme d'une URL complète ("http://serveur:port/application/customers/1234") par rapport au simple chemin ("/application/customers/1234") ?

86voto

Iceberg Points 919

Il y a une subtile ambiguïté conceptuelle lorsque les gens parlent d' "URI relative".

Par la définition de la RFC3986, une URI générique contient :

  URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

  hier-part   = "//" authority path-abempty
              / path-absolute
              / path-rootless
              / path-empty

     foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment

La chose délicate est que, lorsque le schéma et l'autorité sont omis, la partie "chemin" peut elle-même être soit un chemin absolu (commençant par /), soit un chemin relatif "rootless". Exemples :

  1. Une URI absolue ou une URI complète : "http://example.com:8042/over/there?name=ferret"
  2. Et voici une URI relative, avec un chemin absolu : /over/there
  3. Et voici une URI relative, avec un chemin relatif : ici ou ./ici ou ../ici ou etc.

Donc, si la question était "si un serveur devrait produire un chemin relatif dans une réponse restful", la réponse est "Non" et la raison détaillée est disponible ici. Je pense que la plupart des gens (dont moi) qui s'opposent aux "URI relatives" s'opposent en fait aux "chemins relatifs".

Et en pratique, la plupart des frameworks MVC côté serveur peuvent facilement générer des URI relatifs avec un chemin absolu tel que /chemin/absolu/vers/le/contrôleur, et la question devient "si l'implémentation du serveur devrait préfixer un schéma://nomhôte:port devant le chemin absolu". Comme la question de l'auteur original. Je ne suis pas très sûr à ce sujet.

D'un côté, je continue de penser qu'il est recommandé que le serveur renvoie une uri complète. Cependant, le serveur ne devrait jamais intégrer en dur le nomhôte:port dans le code source comme ça (sinon je préférerais tomber en arrière sur une uri relative avec un chemin absolu). La solution est que le serveur obtient toujours ce préfixe à partir de l'en-tête "Host" de la requête HTTP. Pas sûr que cela fonctionne pour toutes les situations cependant.

D'un autre côté, il ne semble pas très contraignant pour le client de concaténer le http://example.com:8042 et le chemin absolu. Après tout, le client connait déjà le schéma et le nom de domaine lorsqu'il envoie la requête au serveur, n'est-ce pas ?

En fin de compte, je dirais, recommander d'utiliser une URI absolue, éventuellement revenir à une URI relative avec un chemin absolu, ne jamais utiliser de chemin relatif.

2 votes

Ceci est une bonne réponse (+1) avec laquelle je suis d'accord, sauf la conclusion finale. Cependant, dans ma réponse, j'argumente que la spécification HTTP définit, par exemple, "absolu" pour se référer à un chemin absolu, et non à un URI entièrement qualifié. Par conséquent, je ne suis pas d'accord avec votre (2) - c'est en fait un URI absolu, mais pour lequel le client doit en inférer le protocole réseau et l'hôte, donc ce n'est pas un URI entièrement qualifié. Et, par conséquent, je ne suis pas d'accord avec votre définition de (1) qui est à la fois un URI complet et un URI absolu.

0 votes

Merci pour le commentaire. Je viens d'emprunter le concept de chemin absolu et relatif du système de fichiers. Termes différents mis à part, je ne vois pas de différence substantielle entre votre opinion et la mienne. Vous recommandez également la forme 1 et 2, et vous êtes contre la forme 3, n'est-ce pas ?

2 votes

Concrètement, je suis pour le (2) ; je pense que le (1) nécessite que le backend ait trop de connaissances spécifiques à HTTP (c'est-à-dire sur les détails de l'environnement HTTP spécifique, pas HTTP en général), et le (3) semble nécessiter trop du client. Mais, mon raisonnement était basé sur le projet initial spécifié, et les exemples ont été modifiés dans une version ultérieure d'une manière qui invalide mon raisonnement.

13voto

Darrel Miller Points 56797

Il dépend de qui écrit le code client. Si vous écrivez à la fois le client et le serveur, cela ne fait pas beaucoup de différence. Vous souffrirez soit de la douleur de la construction des URL sur le client, soit sur le serveur.

Cependant, si vous construisez le serveur et que vous attendez que d'autres personnes écrivent le code client, ils vous aimeront beaucoup plus si vous fournissez des URIs complètes. Résoudre des URIs relatives peut être un peu délicat. Tout d'abord, la façon dont vous les résolvez dépend du type de média renvoyé. HTML a la balise de base, XML peut avoir des balises xml:base dans chaque élément imbriqué, les flux Atom pourraient avoir une base dans le flux et une base différente dans le contenu. Si vous ne fournissez pas d'informations explicites à votre client sur l'URI de base, alors ils doivent obtenir l'URI de base à partir de l'URI de la requête, ou peut-être à partir de l'en-tête Content-Location! Et faites attention à ce slash final. L'URI de base est déterminée en ignorant tous les caractères à droite du dernier slash. Cela signifie que le slash final est maintenant très significatif lors de la résolution d'URIs relatives.

Le seul autre problème qui mérite une petite mention est la taille du document. Si vous renvoyez une longue liste d'éléments où chaque élément peut avoir plusieurs liens, l'utilisation d'URL absolus peut ajouter une quantité significative d'octets à votre entité si vous ne compressez pas l'entité. Il s'agit d'un problème de performance et vous devez décider s'il est significatif au cas par cas.

11voto

Hank Gay Points 36173

La seule véritable différence semblerait être qu'il est plus facile pour les clients s'ils consomment des URI absolues au lieu de devoir les construire à partir de la version relative. Bien sûr, cette différence serait suffisante pour me convaincre de faire la version absolue.

7voto

CyberFonic Points 2218

À mesure que votre application se développe, vous pouvez souhaiter effectuer l'équilibrage de charge, la bascule automatique, etc. Si vous renvoyez des URI absolus, vos applications côté client suivront votre configuration évolutive de serveurs.

1 votes

À condition de définir "absolu" comme un chemin absolu (par exemple, /xxx/yyy...) et non comme signifiant un URI entièrement qualifié (par exemple, http://api.example.com/xxx/yyy...).

2voto

Jay Pete Points 484

Un inconvénient d'utiliser des URI absolus est que l'api ne peut pas être mis en proxy.

Reprenons... pas vrai. Vous devriez opter pour une URL complète incluant le domaine.

3 votes

Pourquoi l'URI absolue ne peut-elle pas utiliser le nom d'hôte du proxy?

1 votes

Travaillant actuellement sur ce problème exact. Nous voulons que toutes les requêtes passent d'abord par une sorte de couche "d'équilibrage de charge". Les URI absolus vers les serveurs directement casseront ce modèle.

1 votes

Je suis en train d'utiliser Nginx pour proxyfier un site avec des URLs absolues. Il est parfaitement capable de remplacer l'URL backend par l'URL de proxy équivalente. Plus précisément, il proxy windyroad.artifactoryonline.com (qui a des URLs entièrement qualifiées et des redirections entièrement qualifiées) vers repo.windyroad.com.au

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X