HTTP : les requêtes conditionnelles
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 :
- Pour la gestion de cache lors d'une requête GET. Le client demande au serveur de lui retourner la représentation de la ressource si cette dernière diffère de la version dont le client dispose déjà.
- Pour garantir l'intégrité des données lors d'une requête non sûre (PUT, POST, PATCH ou DELETE). Le client désire que l'action soit effectuée uniquement si la ressource n'a pas été modifiée depuis son dernier accès.
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
.
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.
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.
Si la ressource n'a pas été modifiée depuis cette date, le serveur devrait retourner le code 304 (Not modified).
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.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).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).
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) :
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
.Si la ressource a effectivement été modifiée, le serveur doit retourner un code 412 (Precondition Failed) :
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êteIf-Match
.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.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).
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) :