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

Les requêtes conditionnelles permettent au client de préciser dans les en-têtes de requête des conditions qui, selon qu'elles sont vraies ou fausses, doivent changer le comportement du serveur. Les requêtes conditionnelles sont utilisées dans deux cas :

Les requêtes conditionnelles peuvent se baser sur la date de dernière modification de la ressource que le serveur est sensé communiqué (principalement en réponse à une requête GET ou HEAD) grâce à l'en-tête de réponse Last-Modified.

Une réponse HTTP avec l'en-tête Last-Modified
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 17
Last-Modified: 

Hello the world!

Les requêtes conditionnelles peuvent également se baser sur l'Entity-Tag. L'Entity-Tag est une chaîne de caractères (délimitée par ") que le serveur peut communiquer (principalement en réponse à une requête GET ou HEAD) grâce à l'en-tête de réponse ETag. Ce tag reste identique tant que la ressource ou sa représentation associée n'ont pas été modifiées. L'Entity-Tag est opaque pour le client et ce dernier n'a pas besoin de connaître l'algorithme utilisé par le serveur pour le produire.

Une réponse HTTP avec l'en-tête ETag
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 17
ETag: ""

Hello the world!

Demander une représentation à jour

Lorsque le client dispose déjà d'une représentation de la resource, il peut demander au serveur de lui retourner une nouvelle représentation uniquement si celle-ci diffère de celle qu'il connaît déjà. L'intérêt principal et de limiter la consommation de bande passante. Mais cela peut aussi être un moyen de savoir si la ressource a été modifiée par un autre client ou un processus asynchrone. Pour ce cas d'utilisation, le client a besoin de connaître la date de dernière modification (obtenue grâce à l'en-tête de réponse Last-Modified) ou la valeur de l'Entity-Tag (obtenue grâce à l'en-tête de réponse ETag)

Le client peut construire sa requête en utilisant l'un des en-têtes suivants :

If-Modified-Since
Permet de spécifier au serveur que la ressource doit avoir été modifiée depuis la date donnée pour traiter la requête.
Requête conditionnelle avec If-Modified-Since
GET /individu/00001 HTTP/1.1
Host: www.monserveur.fr
If-Modified-Since: 

Si la ressource n'a pas été modifiée depuis cette date, le serveur devrait retourner le code 304 (Not modified).

Réponse lorsque la ressource n'a pas été modifiée depuis la date donnée
HTTP/1.1 304 Not Modified
Content-Length: 0

Si la ressource a été effectivement modifiée, le serveur doit traiter la requête normalement.

If-None-Match
Permet de spécifier au serveur que la ressource doit avoir été modifiée depuis le dernier état connu pour traiter la requête. Le client demande au serveur de comparer l'Entity-Tag de la représentation de la ressource avec celui envoyé dans la requête.
Requête conditionnelle avec If-None-Match
GET /individu/00001 HTTP/1.1
Host: www.monserveur.fr
If-None-Match: ""

Si l'Entity-Tag de la représentation de la ressource correspond à celui envoyé par le client, alors le serveur en déduit qu'il n'y a pas eu de modification et il devrait retourner le code 304 (Not modified).

Réponse lorsque l'Entity-Tag correspond à celui envoyé par le client
HTTP/1.1 304 Not Modified
Content-Length: 0

Si les Entity-Tags diffèrent, alors le serveur doit traiter la requête normalement.

Créer une ressource si elle n'existe pas déjà

La méthode PUT a une double sémantique de création et de mise à jour. Cependant, un client désire parfois créer uniquement une ressource et ne souhaite pas la modifier si elle existe déjà. Dans ce cas, on peut utiliser l'en-tête If-None-Match avec la valeur spéciale * (ce qui signifie que le serveur doit traiter la requête si aucune représentation de la ressource n'est disponible).

Requête de création uniquement
PUT /individu/David+Gayerie HTTP/1.1
Host: www.monserveur.fr
If-None-Match: *
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 65

name=Gayerie&firstname=David&email=david.gayerie.epsi@mailoo.org

Si le serveur dispose d'une représentation pour cette ressource (et donc si elle existe déjà), il doit répondre un code 412 (Precondition Failed) :

Réponse lorsque la ressource existe déjà
HTTP/1.1 412 Precondition Failed
Content-Length: 0

Altérer une ressource sous condition

Dans un environnement client/serveur, la mise à jour de données pose systématiquement un problème : comment savoir si les données que je mets à jour n'ont pas été altérées par un autre client depuis le dernier accès. Pour le Web, on trouve plusieurs solutions basées sur le principe du verrou optimiste ou le principe du verrou pessimiste (optimistic/pessimistic lock). HTTP fournit un mécanisme de verrou optimiste grâce à différents en-têtes. Le client peut altérer une ressource avec une méthode PUT, POST, PATCH ou DELETE en spécifiant au serveur la condition de validité de la requête. Pour ce cas d'utilisation, le client a besoin de connaître la date de dernière modification (obtenue grâce à l'en-tête de réponse Last-Modified) ou la valeur de l'Entity-Tag (obtenue grâce à l'en-tête de réponse ETag)

Le client peut construire sa requête en utilisant l'un des en-têtes suivants :

If-Unmodified-Since
Permet de spécifier au serveur qu'il ne doit traiter la requête que si la ressource n'a pas été modifiée depuis la date donnée par l'en-tête If-Unmodified-Since.
Requête conditionnelle avec If-Unmodified-Since
PUT /individu/David+Gayerie HTTP/1.1
Host: www.monserveur.fr
If-Unmodified-Since: 
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 65

name=Gayerie&firstname=David&email=david.gayerie.epsi@mailoo.org

Si la ressource a effectivement été modifiée, le serveur doit retourner un code 412 (Precondition Failed) :

Réponse lorsque la ressource a été modifiée depuis la date donnée
HTTP/1.1 412 Precondition Failed
Content-Length: 0

If-Match
Permet de spécifier au serveur qu'il ne doit traiter la requête que si la ressource n'a pas été modifiée depuis le dernier état connu. Le client demande au serveur de comparer l'Entity-Tag de la représentation de la ressource avec celui donné par l'en-tête If-Match.
Requête conditionnelle avec If-Match
PUT /individu/David+Gayerie HTTP/1.1
Host: www.monserveur.fr
If-Match: ""
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 65

name=Gayerie&firstname=David&email=david.gayerie.epsi@mailoo.org

Si l'Entity-Tag de la représentation de la ressource ne correspond pas à celui envoyé par le client, alors le serveur en déduit que la ressource a été modifiée entre temps et il devrait retourner le code 412 (Precondition failed) sans payload dans la réponse.

Réponse lorsque l'Entity-Tag ne correspond pas à celui envoyé par le client
HTTP/1.1 412 Precondition failed
Content-Length: 0

Si les Entity-Tags sont identiques, alors le serveur doit traiter la requête normalement.

Altérer une ressource si elle existe

Parfois, un client désire modifier une ressource et ne souhaite pas que sa requête soit traitée si elle n'existe pas. Dans ce cas, on peut utiliser l'en-tête If-Match avec la valeur spéciale * (ce qui signifie que le serveur doit traiter la requête si au moins une representation de la ressource est disponible).

Requête de modification uniquement
DELETE /individu/David+Gayerie HTTP/1.1
Host: www.monserveur.fr
If-Match: *

Si le serveur ne dispose pas d'une représentation pour cette ressource (et donc si elle n'existe pas), il doit répondre un code 412 (Precondition Failed) :

Réponse lorsque la ressource n'existe pas
HTTP/1.1 412 Precondition Failed
Content-Length: 0

Exercice : requêtes conditionnelles

Vous devez utiliser l'API Web du site http://rest-bookmarks.herokuapp.com pour expérimenter les requêtes conditionnelles. À partir d'un bookmark que vous aurez créé avec cette API, vous devez utiliser les requêtes conditionnelles pour :

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