« http: » est l'un des services les plus utilisés dans les URL (Uniform Resource Locators) qui sont elles mêmes l'un des deux types d'URI (Uniform Resource Identifiers).
Ce système d'adressage permet non seulement d'identifier les ressources publiées sur le Web mais également de décrire les les liens entre ressources.
HTTP est un protocole client/serveur (dont asymétrique) : un client envoi une requête et le serveur lui renvoi une réponse.
Le protocole HTTP par lui même est sans connexion et sans état, c'est à dire que chaque requête est considérée de manière indépendante sans qu'il ne soit demandé au serveur de mémoriser aucun contexte.
Cela n'interdit pas à un serveur Web de simuler une connexion et de maintenir un état, mais ces pratiques devraient être limitées au maximum afin de respecter les principes architecturaux du Web.
Les documents transmis par les requêtes et les réponses sont décrits en suivant les types mime (rebaptisés « Internet Media Types »), ce qui permet de transmettre tout type de documents, y compris en formats binaires.
HTTP repose sur des principes très simples comme nous pouvons le constater sur cet exemple :
La requête est exprimée par la première ligne :
La « méthode » est « GET » qui signifie « donne moi un document », le document est « / », la version du protocole HTTP utilisée ici est « 1.1 » et il se trouve sur la machine « poweredge.paris.dyomedea.com ».
Les autre lignes sont des « headers » qui apportent des informations complémentaires sur le contexte dans lequel cette requête est effectuée.
GET / HTTP/1.1 Host: poweredge.paris.dyomedea.com User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Epiphany/1.0.8 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Cookie: Apache=10.0.0.2.139451059503845970
La première ligne donne le compte rendu (ici, « 200 » signifie OK). Les lignes suivantes sont des headers donnant des informations complémentaires suivis, après un saut de ligne, par le contenu (ici un document HTML).
HTTP/1.1 200 OK Date: Thu, 10 Jun 2004 12:19:17 GMT Server: Apache/1 .3.26 (Unix) Debian GNU/Linu x PHP/4.1.2 ApacheJServ/1.1.2 Last-Modified: Tue, 27 Aug 2002 16:21:3 6 GMT ETag: " 3a802b-120-3d6ba710" Accept-Ranges: bytes Content-Length: 288 Keep-Alive: timeout =15, max=100 Connection: Keep-Alive Content-Type: text /html; charset =iso-8859-1 <html> <head> <title>Under construction @ dyomedea.com</ title> </head> <body> <h1 align=center>Under construction @<a href="http://dyomedea.com">dyomedea.com</a></h1> < p align="center"> <img src="oeuf.gif"/> <br> <a href="mailto:vdv@dyomedea.com">vdv@dyomedea.com</a > </p> </body> </html>
La sémantique de la méthode « GET » est le téléchargement d'un document.
La spécification HTTP (IETF rfc 2616) indique que cette méthode devrait être « sûre » et ne provoquer aucune action autre que le téléchargement d'une ressource et ne devrait en particulier pas provoquer d'effet de bord au niveau du serveur.
Beaucoup d'applications Web ignorent cette règle.
La sémantique de la méthode « HEAD » est la même que celle de la méthode « GET » sauf que seuls les headers sont renvoyés dans la réponse.
Cette méthode permet donc de tester si un document existe sans le télécharger et de vérifier son type, sa date de modification, ...
La sémantique de la méthode « POST » est le transfert d'information du client vers le serveur.
L'URL associée à la requête POST identifie l'action à effectuer et non l'emplacement auquel les informations transmises sont éventuellement publiées.
Si cette information est publiée sur le serveur et accessible au moyen d'une URL, le serveur peut indiquer cette adresse dans sa réponse. Dans le cas contraire, le serveur renvoi un document servant de compte rendu.
La sémantique de la méthode « PUT » est la mise à jour d'une ressource accessible sur le serveur.
La requête PUT est accompagnée du document à publier et l'URL associée est l'adresse à laquelle ce document doit être publié.
La sémantique de la méthode « DELETE » est l' effacement physique ou logique d'une ressource accessible sur le serveur.
Le protocole HTTP par lui même n' entretient aucune information de connexion ou d'état.
Les application Web, comme toutes les application ont besoin de maintenir un contexte et si le protocole ne le gère pas, elles vont devoir le faire par elles-mêmes.
Le contexte peut être stocké sur le poste client et transmis au serveur à chaque requête notamment dans l'URL (méthode conseillée) ou sous forme de cookies (à éviter).
Le contexte peut également être stocké sur le serveur et le client de transmet plus alors dans ses requêtes qu'une information permettant d'identifier le contexte. Dans ce cas, il est conseillé d' utiliser les méthodes POST, PUT et DELETE pour gérer le contexte.
REST a été introduit en 2000 par Roy Fielding, président de la fondation Apache et membre actif de l'IETF et éditeur de HTTP 1.1 dans le cadre d'une thèse en... philosophie!
Il ne s'agit pas d'un standard, mais d'une série de principes architecturaux permettant aux applications Web de respecter les principes architecturaux du Web et donc de tirer pleinement partie de son potentiel.
Parmi ces principes, le plus notable est la promotion du caractère « sans état et sans connexion » du protocole HTTP au rang de principe de base que les applications ne devraient pas chercher à contourner.
Dans sa thèse, Roy Fielding liste plusieurs lacunes de HTTP qui sont gênantes pour la réalisation de systèmes REST et même une fonctionnalité (les cookies) qui est contraire à ses principes.
On peut donc écrire une application HTTP sans respecter les principes REST et REST peut donc être considéré comme un sous ensemble des fonctionnalités de HTTP.
HTTP étant à la base des applications Web, REST est fortement associé à HTTP mais ne se restreint pas à HTTP.
En tant que principe architectural, REST influence également la manière d'utiliser les URI et les types mime.
En pratique, REST est néanmoins très fidèle à HTTP dans la mesure où il conduit à essayer d'utiliser au mieux les différentes méthodes (GET, POST, PUT, DELETE) mises à notre disposition par HTTP en respectant leur sémantique.
Le premier des « design goals » de XML est d'être facilement utilisable sur Internet et l'association de XML et de HTTP est plus que naturelle.
Et c'est le cas puisque de nombreuse applications réalisent depuis des années des services web sans le savoir en utilisant XML sur HTTP.
Les différentes méthodes HTTP sont bien adaptées à un contenu XML.
La méthode POST est typiquement utilisée pour envoyer un nouveau document XML d'un client vers un serveur (par exemple une commande). En réponse à cette requête, le serveur peut renvoyer un compte rendu sous forme d'un document XML mais également l'adresse à laquelle le document a été stocké et peut être retrouvé, modifié ou supprimé.
La méthode HEAD peut être utilisée pour récupérer des informations sur un document XML et vérifier notamment si le document a été modifié.
La méthode GET peut être utilisé pour interroger un serveur. Elle peut servir à récupérer la commande après que le serveur ait rajouté un numéro de commande.
Lorsqu'il est nécessaire de modifier une information envoyée par POST et publiée par le serveur, on peut utiliser la méthode PUT. Elle peut servir, par exemple, à préciser l'adresse de livraison sur notre commande.
Si l'on souhaite annuler la commande, pourquoi ne pas utiliser la méthode DELETE dont c'est la fonction?
SIRENE -XML est l'un des premiers schémas à avoir été publié sur le répertoire des schémas XML de l'administration (http://www.adae.gouv.fr/upload/documents/architecture.pdf).
Il s'agit d'un service web utilisant HTTP sécurité par SSL (HTTPS) pour donner accès au répertoire SIRENE. Les requêtes et les réponses sont formalisées sous forme de documents XML.
Je pense que l'on peut dire que bien que cette application utilise XML sur HTTP, pelle ourrait être d'avantage conforme aux principes REST qu'elle ne l'est.
Les informations les plus détaillées descendent au niveau de l'établissement. En attribuant une URL à chaque établissement et en publiant les informations concernant l'établissement à cette adresse, on réaliserait une meilleure intégration du système sur le Web.
Dans la mesure où les interrogations sont des opérations « sûres » (sans effet de bord) leur sémantique se rapproche d'avantage de celle d'une méthode GET. L'utilisation de GET interdirait d'exprimer l'interrogation sous forme d'un document XML, mais elle donnerait une URL à chaque requête et rendrait le système facilement utilisable avec un simple navigateur Web.
Parmi le cahier des charges du système de gestion des sondages de XMLfr, ce système devait être distribué sur deux machines et, XMLfr étant implémenté en XSLT, il devait être facilement accessible à partir de XSLT.
La solution technique retenue est une implémentation sous forme de service web utilisant des méthodes HTTP GET et renvoyant les résultats sous forme de documents XML (http://xmlfr.org/documentations/articles/021115-0002).
La transformation XSLT constitue l'adresse à appeler en fonction des informations saisies par les utilisateurs et appelle le traitement en utilisant la fonction « document() ».
Cette solution présente donc le gros avantage d'être immédiatement intégrable dans l'architecture XSLT du site XMLfr.
Le fait d'utiliser une méthode GET pour le vote a facilité l'intégration dans XSLT, mais la sémantique d'un vote est plus proche de celle d'une méthode POST ou PUT puisqu'il s'agit d'envoyer une information au serveur.
Cet écart à une utilisation optimale de HTTP semble donc le prix à payer pour la facilité d'intégration à XSLT.
La question la plus fréquente à propos de REST est sans aucun doute celle de la gestion des états et Paul Prescod en a fourni une très bonne démonstration dans une de ses publications (http://www.prescod.net/rest/state_transition.html).
Son exemple reprend l'épreuve du passage de pont de la mort dans la quête du graal des Monty Python...
Le premier échange est juste une phase d'initialisation décrivant ce qui va se passer par la suite :
--> GET /cross_bridge <-- 200 OK <challenge><p>Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see. Do you agree?</p> If so, <method>GET</method> your next question from <uri>/questions/name_question</uri></challenge>
La première question contient la description de la question ainsi qu'une indication sur la manière de poursuivre l'échange :
--> GET /questions/name_question <-- 200 OK <challenge> <p>Very well. What... is your name?</p> <method>GET</method> the next question by combining your answer with this URI: <uri>/questions/quest_question</uri> </challenge>
Suivant les instructions données dans l'échange précédant, la réponse à la première question est transmise dans l'URL demandant la deuxième question. Comme la première, la deuxième question contient la description de la question et une indication sur la manière de poursuivre les échanges.
--> GET /questions/quest_question?name=Sir+Launcelot+of+Camelot <-- 200 OK <challenge"> <p>What... is your quest? <method>GET</method> the next question by combining your answer with this URI: <uri>/questions/hard_question?name=Sir+Launcelot+of+Camelot</uri></challenge>
La troisième question suit le même principe (patience, nous approchons du but)...
-->
GET /questions/hard_question?name=Sir+Launcelot+of+Camelot
&quest=To+Seek+The+Holy+Grail
<--
200 OK
<challenge>
<p>What... is the air-speed velocity of an unladen swallow?
<method>GET</method> the next question by combining your answer with
<uri>/questions/hard_question?name=Sir+Launcelot+of+Camelot
&quest=To+Seek+The+Holy+Grail</uri></challenge> La réponse finale se fait sur le même principe et l'on note que Paul Prescod va jusqu'à utiliser un code erreur HTTP spécifique pour signifier que la réponse est erronée.
-->
GET /questions/hard_question?name=Sir+Launcelot+of+Camelot
&quest=To+Seek+The+Holy+Grail&air_speed=unknown
<--
406 Not Acceptable
<p>Answer not correct!</p>Un des avantages de cette stratégie est que l'état n'est stocké ni sur le serveur ni sur le client. Il n'y a donc aucun effet de bord puisque le contexte est transféré entre le client et le serveur à chaque échange.
Ce mécanisme élégant est facile à mettre en oeuvre et bien adapté dans le cas de contextes peu volumineux.
REST n'interdit pas de stocker l'état sur le serveur mais recommande dans ce cas de faire bon usage de HTTP et notamment d'utiliser les méthodes suivant leur sémantique.
Le dialogue s'engage de manière similaire à ce que nous avons déjà vu, mais l'on demande au client d'utiliser une méthode « POST » pour publier la confirmation de son engagement dans cet échange.
--> GET /cross_bridge <-- 200 OK <challenge><p>Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see. Do you agree?</p> <method>POST</method> your answer in <uri>/sessions</uri></challenge>
Lorsque la confirmation est postée, le serveur répond en indiquant l'adresse à laquelle elle serait disponible pour consultation et engage à poster la réponse à la première question :
--> POST /sessions <answer continue="true">Ask me the questions, bridgekeeper. I am not afraid.</p> <-- 201 Created Location: /sessions/42 <challenge session="/sessions/42"> <p>Very well. What... is your name?</p> <method>PUT</method> your answer in <uri>/sessions/42/name</uri> </challenge>
Paul Prescod propose de dissocier la réponse à la première question de la demande de la deuxième question :
--> PUT /sessions/42/name <answer continue="true">My name is 'Sir Launcelot of Camelot'</answer> <-- 201 Created Location: /sessions/42/name ...
Ici, /sessions/42/name est l'adresse à laquelle le nom pourrait être consulté ou modifié et il ne serait pas très propre d'utiliser cette adresse pour publier la deuxième question.
La deuxième question est communiquée par un nouvel accès à /sessions/42 :
--> GET /sessions/42 <-- 200 OK <challenge session="/sessions/42"> <name href="/sessions/42/name"/>, <p>what... is your quest? <method>PUT</method> your answer in <uri>/sessions/42/quest</uri></challenge>
Il y a donc bien gestion d'un état au niveau du serveur puisque le document renvoyé à l'adresse /sessions/42 dépend des documents déjà postés sur le serveur. Ce n'est pas interdit par REST dans la mesure où nous avons utilisé les différentes méthodes conformément à leur sémantique.
Notons également que pour faciliter les développements, la session donne toutes les informations nécessaires pour récupérer les informations.
Nous avons montré comment dissocier la réponse et l'interrogation de la session, mais HTTP n'interdit pas de renvoyer la description de la session en réponse à un « PUT » et nous pouvons le faire pour optimiser le dialogue :
--> PUT /sessions/42/quest <answer continue="true">To seek the Holy Grail.</answer> <-- 201 Created Location: /sessions/42/quest <challenge session="/sessions/42"> <name href="/sessions/42/name"/>, <quest href="/quest="/sessions/42/quest"/> <p>What... is the air-speed velocity of an unladen swallow? <method>PUT</method> your answer in <uri>/sessions/42/hard_question</uri></challenge>
--> PUT /sessions/42/hard_question <answer continue="confused">Err....What do you mean? An African or European swallow?</answer> <-- 406 Not Acceptable <p>Answer not correct!</p>
L'état est stocké et géré par le serveur conformément aux principes REST et en respectant la sémantique des méthodes HTTP.
Chaque session a son URL (dont la durée de vie peut être limitée) et l'interrogation de cette URL permet de connaître en détail l'état de la session.
Chaque réponse a également son URL qui peut être consultée pour vérification.
Cet exemple est facilement généralisable, par exemple à celui d'une gestion de commandes.
Eric
van der Vlist (vdv@dyomedea.com)
–REST-- WS Convention 2004 -- Page