Services Web - EPSI POE mars 2017 - David Gayerie Licence Creative Commons

À travers différents cas d'utilisation, nous allons clarifier le rôle des méthodes HTTP et exploiter différents codes statut.

Obtenir la représentation d'une ressource

Lorsqu'un client désire obtenir la représentation d'une ressource auprès d'un serveur, il utilise toujours la méthode GET. En cas du succès, le serveur doit répondre le code 200 ainsi que la représentation de la ressource.

La requête
GET /web+service HTTP/1.1
Host: www.dictionary.info

La réponse du serveur en cas de succès
HTTP/1.1 200 OK
Content-type: text/plain; charset=utf-8
Content-language: en
Content-length: 226

A Web Service is a method of communication between two electronic devices over a network.
It is a software function provided at a network address over the web with the service always on 
as in the concept of utility computing.

Obtenir uniquement les meta-informations d'une ressource

Un client peut souhaiter obtenir des meta-informations sur une ressource. Par exemple, il souhaite vérifier qu'une ressource existe sans nécessairement obtenir sa représentation. Dans ce cas, il doit utiliser la méthode HEAD. Cette méthode se comporte comme la méthode GET mais sans retourner le corps du message

La requête
HEAD /web+service HTTP/1.1
Host: www.dictionary.info

La réponse du serveur en cas de succès
HTTP/1.1 200 OK
Content-type: text/plain; charset=utf-8
Content-language: en
Content-length: 226

Créer une ressource dont on connait l'URI

Lorsqu'un client veut créer une ressource sur le serveur, il faut distinguer le cas où le client connaît l'URI finale de la ressource du cas où c'est au serveur de déterminer l'URI finale. Dans le cas où l'utilisateur connaît l'URI, la méthode sera toujours un PUT. En cas de succès, le serveur devrait répondre le code 201.

La requête
PUT /individu/David+Gayerie HTTP/1.1
Host: exemple.fr
Content-type: application/json; charset=utf-8
Content-length: 91

{"name" : "Gayerie", 
 "firstname" : "David", 
 "email" : "david.gayerie.epsi@mailoo.org"}
La réponse du serveur en cas de succès
HTTP/1.1 201 Created
Content-length: 0

Dans l'exemple ci-dessus, le client souhaite créer une nouvelle ressource identifiée par l'URI http://exemple.fr/individu/David+Gayerie.

Créer une ressource dont on ne connait pas l'URI

Dans le cas où l'utilisateur ne connaît pas l'URI finale de la ressource, la méthode sera toujours un POST. En cas de succès, le serveur devrait répondre le code 201 et un en-tête Location donnant au client l'URI de la nouvelle ressource.

La requête
POST /individu/ HTTP/1.1
Host: exemple.fr
Content-type: application/x-www-form-urlencoded; charset=utf-8
Content-length: 65

name=Gayerie&firstname=David&email=david.gayerie.epsi@mailoo.org
La réponse du serveur en cas de succès
HTTP/1.1 201 Created
Location: http://exemple.fr/individu/000001
Content-length: 0

Dans l'exemple ci-dessus, le client souhaite créer une ressource et le serveur décide d'identifier cette nouvelle ressource par l'URI http://exemple.fr/individu/000001. Dans ce cas, la méthode POST a la sémantique d'un ajout d'une ressource à un ensemble (celui des individus).

Supprimer l'accès à une ressource

La requête
DELETE /individu/000001 HTTP/1.1
Host: exemple.fr

La réponse du serveur en cas de succès
HTTP/1.1 204 No content

Mettre à jour une ressource

La mise à jour complète d'une ressource existante se fait grâce à la méthode PUT.

La requête
PUT /individu/David+Gayerie HTTP/1.1
Host: exemple.fr
Content-type: application/json; charset=utf-8
Content-length: 91

{"name" : "Gayerie", 
 "firstname" : "David", 
 "email" : "david.gayerie.epsi@mailoo.org"}
La réponse du serveur en cas de succès
HTTP/1.1 204 No content

La requête de l'exemple ci-dessus est strictement identique à celle de la section Créer une ressource dont on connait l'URI. Seule la réponse du serveur fait la différence : 204 signifie que la requête a été acceptée mais sans préciser une création (cela signifie que l'opération a été une mise à jour). Le client ne sait pas a priori s'il demande une création ou une modification. Cela correspond parfaitement à la caractéristique d'idempotence de la méthode PUT : la requête peut donc être répétée 1 à N fois et produira la même résultat sur le serveur.

Mettre à jour partiellement une ressource

La méthode PATCH a été introduite par la RFC 5789 afin de fournir une méthode pour la mise à jour partielle d'une ressource.

La requête
PATCH /individu/David+Gayerie HTTP/1.1
Host: exemple.fr
Content-type: application/json-patch+json; charset=utf-8
Content-length: 53

{"op" : "add", 
 "path" : "/taille", 
 "value" : 174}
La réponse du serveur en cas de succès
HTTP/1.1 204 No content

La difficulté de l'utilisation de la méthode PATCH vient de la nécessité pour le serveur et le client de partager un format de représentation permettant de décrire les modifications à apporter. L'exemple précédent utilise le format JSON patch proposé par la RFC 6902. Le client demande au serveur d'ajouter l'attribut "taille" à la ressource avec pour valeur le nombre 174. JSON patch a précisément été créé pour être utilisé conjointement avec la méthode PATCH.

Exécuter un processus de traitement

Il est parfois utile de demander à un serveur de traiter de l'information pour obtenir un résultat. Le résultat n'est pas une ressource dont le serveur serait le dépositaire. Il s'agit juste d'une information qui est calculée mais non conservée par le serveur. Dans ce cas, le client doit utiliser la méthode POST.

La requête
POST /calculatrice HTTP/1.1
Host: www.monserveur.fr
Content-Type: application/x-www-form-urlencoded
Content-Length: 40

operande=2&operande=3&operation=addition
La réponse du serveur en cas de succès
HTTP/1.1 200 OK
Content-type: text/plain
Content-length: 1

5

Connaître les méthodes autorisées

Si un client tente d'appliquer une méthode HTTP interdite sur une ressource, le serveur répond généralement par le code statut 405 (Method not allowed).

Afin de permettre au client d'être informé de la liste des méthodes autorisées pour une URI, le serveur peut ajouter l'en-tête Allow dans sa réponse. Cet en-tête liste les méthodes autorisées séparées par une virgule.

Le client peut également émettre une requête avec la méthode OPTIONS pour obtenir cet en-tête Allow :

La requête
OPTIONS /individu/David+Gayerie HTTP/1.1
Host: exemple.fr

La réponse du serveur en cas de succès
HTTP/1.1 200 OK
Content-length: 31
Content-type: text/plain
Allow: GET, HEAD, DELETE, PUT, OPTIONS

GET, HEAD, DELETE, PUT, OPTIONS

Traitement asynchrone d'une requête

Parfois, le serveur ne peut pas traiter complètement une requête dans un temps acceptable. Dans ce cas, il peut retourner le code 202 qui signifie qu'il a bien compris et accepté la requête mais qu'il ne l'a pas encore traitée.

La requête
DELETE /individu/000001 HTTP/1.1
Host: exemple.fr

La réponse du serveur lorsque la requête est traitée en asynchrone
HTTP/1.1 202 Accepted
Location: http://exemple.fr/jobs/1948321
Content-type: text/plain
Content-length: 53

Traitement http://exemple.fr/jobs/1948321 en cours...

Dans l'exemple ci-dessus, la requête a conduit à la création d'une ressource temporaire représentant le traitement en cours. L'en-tête Location donne l'URI où le client pourra se rendre pour consulter l'état du traitement.

Les redirections

Les redirections correspondent aux codes statut de la famille 3XX. Elles permettent au serveur de réorienter le client vers une nouvelle URI. À la réception d'un code de redirection, le client doit comprendre que pour terminer sa requête, il doit exécuter une nouvelle requête vers une URI fournie dans la réponse par le serveur grâce à l'en-tête Location.

Évolution du service

Le cas le plus simple d'utilisation des redirections est celui où le serveur évolue dans le temps. Des évolutions peuvent entraîner une modification des URI. Plutôt que de retourner simplement une erreur, le serveur propose une redirection pour assurer une continuité du service. Dans ce cas, le serveur peut retourner un code statut 301 (Moved Permanently) avec un en-tête Location donnant la nouvelle URI.

Le serveur signale un changement de l'URI du service
HTTP/1.1 301 Moved Permanently
Location: http://mon.nouveau.serveur.fr/ma/ressource/cible

URI volatile et canonicalisation d'URI

Nous verrons que dans une architecture REST, une ressource ne doit être identifié que par une seule URI. Pourtant il existe de nombreux cas d'utilisation où l'on désire rendre accessible la representation d'une ressource à partir de différentes URI. Par exemple, imaginons une suite de news, chaque article dispose de sa propre URI mais on peut souhaiter exposer une URI permettant d'accéder au dernier article publié. Cette URI désignera forcément dans le temps des ressources différentes. Elle est volatile. Dans ce cas, le serveur peut retourner pour cette URI le code statut 307 (Temporary redirect) qui demande au client de refaire la même requête vers l'URI donnée en réponse par l'en-tête Location.

Requête sur une URI volatile
GET /articles/latest HTTP/1.1
Host: www.mynews.fr

Redirection du serveur...
HTTP/1.1 307 Temporary redirect
Location: http://www.mynews.fr/articles/les+nouvelles+du+monde.html

La redirection est coûteuse car elle oblige le client à émettre une nouvelle requête vers le serveur. Si le serveur peut répondre directement, il peut renvoyer une code 2XX avec le message attendu et ajouter l'en-tête de réponse Content-Location qui indique au client la véritable URI pour cette ressource (appelée URI canonique).

... ou canonicalisation grâce à l'en-tête Content-Location
HTTP/1.1 200 OK
Content-Location: http://www.mynews.fr/articles/les+nouvelles+du+monde.html
Cache-control: no-store
Content-type: text/plain
Content-length: 35

Il n'y pas de nouvelle du monde :(

Séparer le traitement de la requête de son résultat

Nous avons vu précédemment qu'il est possible de réaliser des requêtes asynchrones en HTTP. Mais il existe d'autres cas pour lesquels le serveur ne souhaite pas retourner directement de réponse au client.

Dans la navigation Web, un cas répandu est le POST/Redirect/GET. La méthode POST n'est pas idempotente. Lorsqu'un utilisateur remonte dans son historique de navigation jusqu'à une requête POST, le navigateur n'a pas d'autre choix que de demander à l'utilisateur s'il désire soumettre à nouveau cette requête. Il est donc souhaitable de faire disparaître les méthodes non idempotentes de l'historique de navigation. Or un navigateur Web ne conserve pas l'historique d'une requête dont la réponse est une redirection (ou plus exactement, il lui substitue la requête de redirection). Il est donc possible de supprimer les requêtes POST de l'historique de navigation en s'assurant que les réponses sont toujours des redirections avec une méthode GET vers une page de résultat : il s'agit du modèle du POST/Redirect/GET. Pour cela, le développeur de site Web doit s'assurer que le code statut en réponse à une méthode POST est un code 303 (See Other). L'en-tête de réponse Location indique à quelle URI le client doit soumettre la requête GET de redirection.

Une requête POST
POST /individu/ HTTP/1.1
Host: exemple.fr
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 65

name=Gayerie&firstname=David&email=david.gayerie.epsi@mailoo.org
La réponse du serveur avec une redirection
HTTP/1.1 303 See Other
Location: http://exemple.fr/individu/000001

Exercice : utilisation d'une API Web

Vous devez utiliser l'API Web du site http://rest-bookmarks.herokuapp.com pour réaliser les opérations suivantes :

Vous devez fournir la liste des commandes cURL pour réaliser les actions ci-dessus.