title:      ★ L&#39;architecture orientée ressource pour faire des services web RESTful
slug:       architecture-orientee-ressource-pour-faire-des-services-web-restful
date:       2007-06-29 23:13:11
type:       post
vignette:   
contextual_title1:  ★ Django-ROA, pour une architecture orientée ressources
contextual_url1:    20090526-django-roa-pour-une-architecture-orientee-ressources
contextual_title2:  ★ Architecture web moderne et agile
contextual_url2:    20080604-architecture-web-moderne-et-agile
contextual_title3:  Critique du livre RESTful Web Services
contextual_url3:    20070830-critique-du-livre-restful-web-services

<p>Le plus gros défaut de <abbr title="REpresentational State Transfer">REST</abbr>, c'est sûrement de se limiter à la comparaison des 4 verbes HTTP (GET, POST, PUT et DELETE) aux 4 actions possibles sur des données issues de bases de données (Retrieve, Create, Update et Delete soit CRUD mais j'ai laissé dans l'ordre de la comparaison). Et le pire, c'est que je suis tombé dans ce «&nbsp;piège » dans mon <a href="https://larlet.fr/david/biologeek/archives/20070413-pour-ne-plus-etre-en-rest-comprendre-cette-architecture/">précédent billet sur REST</a> (même si c'était une traduction), il est temps de parler plus en détail des possibilités offertes par une telle architecture.</p>

<h2>Préambule</h2>


<p>Pour être tout à fait honnête, ce billet est grandement inspiré du chapitre 4 du livre <a href="http://www.oreilly.com/catalog/9780596529260/">RESTful WebServices</a>, document que vous pourrez librement télécharger sur l'<a href="http://www.infoq.com/articles/richardson-ruby-restful-ws">article présentant une interview des auteurs</a>. Ce livre est <a href="http://www.beckshome.com/PermaLink,guid,239228b4-c9ba-4263-834d-b4ac87918cb4.aspx">comparé à celui du Gang Of Four en terme d'impact</a> donc il faut absolument que je me le procure car ce chapitre m'a clairement mis l'eau à la bouche&nbsp;! Il y a même un chapitre qui parle de <a href="https://larlet.fr/david/biologeek/archives/20070501-developper-une-application-restful-avec-django/">REST dans Django</a> :-).</p>


<p>Christian a fait une <a href="http://www.christian-faure.net/2007/06/22/restful-web-services/">excellente note d'introduction à l'enjeu de cet ouvrage</a> si vous souhaitez avoir une version plus «&nbsp;haut niveau ».</p>


<p>La terminologie <strong>architecture orientée ressource</strong> est presque une pure création des auteurs, il s'agit de préciser certains points de l'architecture REST afin d'en avoir la même interprétation pour tous. Ce sont surtout des <strong>règles ou bonnes pratiques de REST appliquées au domaine des services web</strong> (qui peuvent être transgressées si l'on en comprend bien les tenants et les aboutissants). Ces règles me semblent essentielles pour ne pas dériver vers du <a href="http://duncan-cragg.org/blog/post/strest-service-trampled-rest-will-break-web-20/"><abbr title="Service-Trampled REST">STREST</abbr> 2.0</a>, ce qui est bien trop souvent le cas...</p>


<p>Enfin l'utilisation du terme architecture orientée ressource permet justement de se différencier du terme REST qui est utilisé aujourd'hui un peu à tort et à travers. L'architecture REST étant très vague, les différentes interprétations sont à l'origine de véritables guerres entre extrêmistes que les auteurs ne cautionnent pas. Voici donc <strong>les 4 concepts et les 4 propriétés décrivant une architecture orientée ressource</strong>&nbsp;:</p>


<h2>Concepts</h2>


<h3>Les ressources</h3>


<blockquote><p>Une ressource est quelque chose d'assez important pour être référencé comme étant une chose en elle-même.</p></blockquote>


<p>En énonçant cela, on a à la fois tout dit et rien dit&nbsp;! Donc plongeons un peu plus dans le détail avec <a href="http://www.opikanoba.org/tr/w3c/webarch/#p39">un extrait du <abbr title="World Wide Web Consortium">W3C</abbr></a>, si vous souhaitez&nbsp;:</p>


<blockquote><p>créer un lien hypertexte vers elle, faire ou réfuter des affirmations à son sujet, rechercher ou mettre en mémoire cache une représentation la concernant, l'inclure en partie ou dans son ensemble en la référençant dans une autre représentation, l'annoter ou encore effectuer d'autres opérations</p></blockquote>


<p>alors vous devez créer une ressource. <strong>Une ressource peut donc être un objet physique ou un concept abstrait.</strong></p>


<h3>Leurs noms (<abbr title="Uniform Resource Identifier">URI</abbr>)</h3>


<p>Mais pour qu'une ressource soit connue, il faut qu'elle soit accessible et pour ça on a créé les URI qui sont à la fois le nom et l'adresse d'une ressource, <strong>sans URI pas de ressource</strong>.</p>


<p>C'est ce qui fait la force du Web (HTTP), et ce qui lui a permis d'écraser une bonne partie des autres protocoles. Aujourd'hui tout passe par ce protocole au détriment des autres, on télécharge via un navigateur et non un client FTP par exemple.</p>


<p>L'un des points importants de l'architecture orientée ressource est qu'<strong>une URI doit être descriptive</strong>. On doit savoir ce qui se cache derrière une URI rien qu'en la lisant, par exemple en allant sur http://www.biologeek.com/liens/ vous savez que vous allez accéder à une page listant des liens. On peut même aller jusqu'à prédire et donc construire des URI, ce à quoi je me suis attaché dans ma refonte, pour pouvoir par exemple construire http://www.biologeek.com/python,django,rest/ si je souhaite avoir tous les billets formant l'intersection de ces thèmes.</p>


<p>Enfin un mot sur la relation URI/ressource&nbsp;: une ressource doit au moins avoir une URI mais rien n'empêche une ressource d'avoir plusieurs URI. C'est néanmoins déconseillé pour deux raisons&nbsp;:</p>

<ul>
<li><strong>la dilution de l'information</strong> (bon il y a aussi le problème du duplicate content de google...)&nbsp;;</li>
<li><strong>la possible incompréhension</strong> du «&nbsp;visiteur » (est-ce vraiment la même ressource ?).</li>
</ul>

<h3>Leurs représentations</h3>


<p>Le découpage en ressources est conceptuel, une ressource n'est pas une donnée. Il faut donc représenter cette ressource sous format informatique pour qu'elle soit consultable, cette représentation peut avoir différents formats (html ou json par exemple).</p>


<p>Ce qui est recommandé en termes d'architecture orientée ressource est de <strong>faire figurer les informations de représentation au sein de l'URI</strong>. Alors bien sûr ça va faire bondir ceux qui connaissent les headers permettant justement de préciser ce type d'information sous forme de méta-données mais les auteurs avancent deux arguments qui me semblent pertinents&nbsp;:</p>

<ul>
<li><strong>sur le plan humain</strong>, lorsqu'on donne une URI à quelqu'un, on souhaite qu'il ait la même représentation de la ressource que nous&nbsp;;</li>
<li><strong>sur le plan machine</strong>, les robots (comme le validateur du W3C ou les crawlers) ne vont pas pouvoir tester/répertorier l'ensemble de vos représentations.</li>
</ul>

<h3>Les liens entre elles</h3>


<p>Les représentations ne contiennent bien souvent pas seulement des données mais aussi des liens vers d'autres ressources. L'axiome issu de la <a href="http://opikanoba.org/tr/fielding/rest/">thèse de Roy Fielding</a>&nbsp;:</p>


<blockquote><p>l'hypermédia comme moteur de l'état de l’application</p></blockquote>


<p>Résume bien le fait que <strong>nous naviguons sur internet</strong> grâce aux liens entre les ressources. Que votre page d'accueil soit un moteur de recherche ou celle de votre <abbr title="Fournisseur d&#039;Accès à Internet">FAI</abbr> préféré, ce n'est qu'un point d'entrée pour aller consulter des ressources. Sans ces outils d'agrégation que de temps <del>gagné pour arrêter de geeker</del> perdu à chercher les ressources nécessaires...</p>


<h2>Propriétés</h2>


<h3>À adresse</h3>


<blockquote><p>Une application à adresses doit pouvoir présenter les aspects intéressants de son jeu de données sous la forme de ressources.</p></blockquote>


<p>Comme les ressources sont identifiées par leurs URI, ça consiste généralement à fournir une liste d'URI possibles. Celles-ci pouvant être infinies comme par exemple dans le cas de Google&nbsp;: http://www.google.fr/search?q=* où * peut être remplacé par n'importe quel mot-clé, par exemple http://www.google.fr/search?q=rest . Grâce à cette propriété, on peut indiquer une adresse à quelqu'un sans lui dire&nbsp;: va sur google.fr et tape «&nbsp;rest » dans le formulaire.</p>


<p>C'est le gros problème des applications web 2.0 actuelles qui utilisent AJAX, elles ne sont pas toujours à adresses. En fait <strong>ces services sont souvent déjà des clients de services web RESTful</strong>. Par exemple dans le cas de GMail, http://mail.google.com/mail/ est le client et http://mail.google.com/mail/?ui=html est le service web qui vous permet de donner une adresse de recherche dans les mails par exemple (ce qui serait impossible avec la version client/AJAX). <strong>La perte des adresses dans de telles applications est problématique et il devrait toujours être possible d'avoir le lien direct vers les ressources présentées</strong> (puisqu'il n'est pas possible de changer l'adresse du navigateur en JavaScript, excepté les ancres).</p>


<h3>Sans état</h3>


<p><strong>Chaque requête HTTP doit s'exécuter sans avoir connaissance des requêtes précédentes ou suivantes.</strong> C'est l'une des propriétés clés de l'architecture orientée ressource qui permet par exemple de ne pas casser le bouton «&nbsp;Reculer d'une page » du navigateur. Chaque nouvelle page affichée contient toutes les informations nécessaires pour afficher la ressource appropriée ou effectuer les traitements nécessaires, <strong>les requêtes ne doivent pas avoir d'ordre pré-défini et sont déconnectées les unes des autres</strong>.</p>


<p>De cette façon, <strong>le serveur n'a jamais besoin de connaître l'état du client</strong>, il ne sait même pas où il est, il sait juste qu'une requête arrivant avec tels paramètres doit restituer telles données. C'est un réel avantage lorsque vous fournissez un tel service car vous pouvez mettre des requêtes en cache de manière performante ou jouer avec du load-balancing sans avoir à vous soucier de ce qu'il se passe sur les autres serveurs.</p>


<p><strong>Les cookies et les sessions sont les deux possibilités habituelles pour casser une telle architecture</strong>. Leur utilisation donne au serveur la possibilité de connaître l'état de ses différents clients ce qui va par exemple modifier la représentation d'une ressource selon le client qui va l'afficher. C'est une grave violation de l'architecture orientée ressource.</p>


<p>Mais de quel état parle-t-on&nbsp;? Celui de l'application ou celui de la ressource&nbsp;?</p>


<p><strong>Il faut avant tout distinguer l'état de l'application, qui est dépendante du client, et l'état de la ressource, qui est dépendante du serveur</strong>. Un service web ne doit prendre en compte l'état de votre application qu'au moment de la requête et vous devez donc envoyer toutes les informations nécessaires à ce moment là. L'état d'une ressource est le même pour toutes les requêtes.</p>


<p>Prenons un exemple assez insidieux, celui des clés d'API. Si votre clé ne vous permet d'effectuer qu'un nombre limité de requêtes (comme c'est le cas pour celle de Google), alors c'est un état du client. Vous allez pouvoir effectuer les 1000 premières requêtes mais la 1001ème ne sera pas possible, c'est donc différent selon le client.</p>


<h3>Connecté</h3>


<p>Cette propriété est directement issue du concept des liens évoqué ci-dessus. <strong>Les ressources doivent s'inter-lier dans leurs représentations respectives</strong>. Si l'on prend le service <a href="http://www.amazon.com/gp/browse.html?node=16427261">S3 d'Amazon</a> par exemple, les ressources sont accessible via un service RESTful mais elles ne sont pas connectées.</p>


<p>J'ai par exemple l'habitude de dire qu'un billet de blog sans liens est une impasse, je trouve que cette image illustre parfaitement cette propriété.</p>


<h3>À interface uniforme</h3>


<p>Et cette interface provient des verbes HTTP, je ne vais pas reprendre en détail ce que j'ai déjà expliqué dans le <a href="https://larlet.fr/david/biologeek/archives/20070413-pour-ne-plus-etre-en-rest-comprendre-cette-architecture/">précédent billet sur REST</a> mais plutôt revenir sur des points de détails qui ont leur importance. Si l'on considère les 4 verbes les plus intéressants, bref rappel tout de même&nbsp;:</p>

<ul>
<li><strong>GET</strong> permet de récupérer une représentation d'une ressource&nbsp;;</li>
<li><strong>POST</strong> de créer une ressource&nbsp;;</li>
<li><strong>PUT</strong> de mettre une ressource à jour&nbsp;;</li>
<li><strong>DELETE</strong> de supprimer la ressource.</li>
</ul>

<p>Avec une remarque concernant la création d'une ressource, il est aussi possible d'utiliser <strong>PUT</strong> si l'on connaît l'URI finale de la ressource. Généralement <strong>POST</strong> est utilisé car l'on peut difficilement connaître l'id sous lequel la ressource va être enregistrée par le serveur par exemple et cet id se retrouve souvent dans l'URI de la ressource.</p>


<p>Autre remarque concernant cette fois <strong>POST</strong>, il est possible d'ajouter des données à une ressource via ce verbe. Un bon exemple est celui d'une ressource de type log, comment faire pour ajouter une entrée à la fin de /log/&nbsp;? La sémantique de <strong>POST</strong> permet d'ajouter une nouvelle ligne comme si cela était une nouvelle ressource de type particulier (qui ne possède pas forcément d'URI...).</p>


<p>Enfin les auteurs distinguent le <strong>POST(a) d'ajout</strong> qui est celui correspondant à l'architecture REST et le <strong>POST(o) surchargé</strong> (overloaded) qui est celui utilisé par les navigateurs et qui ne permet pas de différencier les différents verbes possibles (POST, PUT ou DELETE). Je trouve que c'est une bonne nomenclature et j'aurais l'occasion de la réutiliser ici.</p>


<p>Il existe aussi les verbes <strong>HEAD</strong> et <strong>OPTIONS</strong> qui peuvent vous être utiles&nbsp;:</p>
<ul>
<li><strong>HEAD</strong>&nbsp;: permet de récupérer uniquement les méta-données&nbsp;;</li>
<li><strong>OPTIONS</strong>&nbsp;: permet de connaître les verbes autorisés pour une URI donnée.</li>
</ul>

<p>Enfin concernant l'interface uniforme, deux propriétés à ne pas oublier&nbsp;:</p>
<ul>
<li>la <strong>sûreté</strong>&nbsp;: lorsque les verbes <strong>GET</strong> ou <strong>HEAD</strong> sont employés, c'est pour lire des données et il ne doit donc y avoir <strong>aucun changement d'état au niveau du serveur</strong>. C'est la raison principale pour laquelle les boutons d'un formulaire sont si <del>moches</del> <a href="http://meyerweb.com/eric/thoughts/2007/05/15/formal-weirdness/">reconnaissables</a>, l'utilisateur doit être averti lorsqu'il risque de modifier des données sur le serveur. Un bon exemple des problèmes que cela peut engendrer est le client <a href="http://webaccelerator.google.com/support.html">Web Accelerator</a> que Google avait lancé en 2005 et qui devait précharger les pages suivantes possibles (accessibles en GET) pour les afficher plus rapidement. Si tous les sites avaient respecté cette propriété, il n'y aurait pas eu des milliers de comptes/mails/etc effacés... résultat, cet outil a été un flop&nbsp;;</li>
<li>l'<strong><a href="http://fr.wikipedia.org/wiki/Idempotence">idempotence</a></strong>&nbsp;: traduit en REST, il s'agit de pouvoir répéter une requête plusieurs fois sans que cela ait de conséquences. Imaginons un billet de blog, je peux faire autant de <strong>GET</strong> que je veux dessus sans que ça pose problème, pareil pour <strong>PUT</strong> puisque nous avons vu que toutes les informations doivent être envoyées à chaque requête selon la propriété <strong>sans état</strong> plus haut. Dans le cas de <strong>DELETE</strong>, je vais aussi pouvoir répéter plusieurs fois la même opération aussi, la première supprimera effectivement la ressource, les suivantes pourront m'informer que cela a déjà été fait mais je pourrais les faire. <strong>Le véritable problème de l'idempotence intervient lors des POST</strong>. Plusieurs mécanismes de confirmation existent mais ça sera sûrement pour un prochain billet :-).</li>
</ul>

<h2>Conclusion</h2>


<p>J'espère que ce billet vous aura permis de comprendre un peu mieux les règles qui régissent une architecture REST et par extension une architecture orientée ressource. <strong>Il ne s'agit pas de la nouvelle architecture 2.0 hype du moment mais bien du Web passé, actuel et futur donc en le comprenant vous pourrez construire des sites et des applications web mieux pensées et cohérentes</strong>. Vous gagnerez en interopérabilité mais aussi en temps de développement puisque votre API sera la même pour votre propre client et pour les utilisateurs qui souhaitent développer des applications tierces. <strong>Une fois les concepts et les propriétés assimilés, il n'y a vraiment que des avantages à utiliser une telle architecture</strong>.</p>
