Date de publication du RFC : Juin 2014
Auteur(s) du RFC : J. Snell
Chemin des normes
Première rédaction de cet article le 18 juin 2014
Dans certains cas, la norme du protocole
HTTP laisse un serveur choisir entre plusieurs
comportements, tous légaux. Un client peut avoir une préférence
personnelle et ce nouvel en-tête Prefer:
, dans la
requête HTTP, permet à ce client de la spécifier. Ce n'est pas un
ordre, le serveur peut ignorer cette préférence.
Un exemple de cette latitude laissée aux serveurs ? Lorsqu'un
client modifie une ressource Web avec la commande
PUT
(cf. RFC 5023), le
serveur peut retourner la nouvelle ressource, complète, ou bien
seulement la modification faite. Le client pourrait dire « je ne vais
même pas lire ce texte, envoie le minimum » ou bien « je vais tout
vérifier soigneusement, envoie la ressource après modification, pour
m'éviter un GET
ultérieur ». Le peut-il
aujourd'hui avec l'en-tête Expect:
(section 14.20
du RFC 2616) ? Non, car
Expect:
est impératif : tout serveur, ou même
tout intermédiaire (par exemple un relais) qui
ne le comprend pas, ou ne peut lui obéir, doit rejeter la
requête. Expect:
ne convient donc pas pour le cas
où on veut dire « si tu arrives à le faire comme cela, ça
m'arrangerait mais ne te casse pas trop la tête ». Comme le dit le
RFC, dans un style très Jane Austen,
« preferences cannot be used as expectations ». C'est
d'autant plus important que certaines préférences peuvent avoir un
coût de traitement élevé pour le serveur et que, si celui-ci les
acceptait aveuglément, il pourrait se retrouver victime d'un
déni de service (cf. section 6).
La section 2 spécifie la syntaxe du nouvel en-tête
Prefer:
. Sa sémantique, on l'a vu, est qu'il n'est
pas impératif. Le serveur qui ne comprend pas un
Prefer:
ou ne peut pas ou ne veut pas le
respecter continue le traitement de la requête en ignorant cet
en-tête. Il peut y avoir plusieurs en-têtes
Prefer:
ou bien un seul avec une liste de
préférences séparées par des virgules, comme ici :
GET /coffee HTTP/1.1 Prefer: no-sugar, no-milk, hot
Certaines préférences prennent une valeur, après un signe = :
GET /coffee HTTP/1.1 Prefer: sugar=2
Il peut aussi y avoir des paramètres à certaines préférences, après un ; comme :
GET /coffee HTTP/1.1 Prefer: milk; organic="true"
Vu le caractère optionnel de ce système de préférences, on ne
s'étonnera pas que le RFC demande aux serveurs HTTP d'ignorer les
préférences inconnues (ce qui est le cas de milk
ou sugar
, qui ne sont pas dans le registre officiel...)
Que peut-on mettre dans un champ
Prefer:
? Uniquement des préférences enregistrées. La section 4 décrit les préférences
existant actuellement :
respond-async
indique que le client n'aime
pas attendre et préfère une réponse asynchrone plus tard. Le serveur
qui acceptera enverra alors un code de retour 202, accompagné d'un
champ Location:
pour indiquer où récupérer la
réponse lorsqu'elle sera prête. Cette préférence ne prend pas de
valeur.wait
prend une valeur, le nombre de
secondes qu'on est prêt à attendre, ce qui est utile en combinaison
avec respond-async
. Ainsi, Prefer:
respond-async, wait=30
signifiera qu'on est prêt à attendre
une demi-minute, puis qu'on préférerait une réponse asynchrone
ensuite.return
a aussi une
valeur, indiquant si le client préfère recevoir la ressource entière
ou bien une version allégée. Prefer:
return=representation
exprime le premier choix et
Prefer: return=minimal
le second (c'est sans
doute ce que demanderont les clients connectés à un réseau très lent).handling
indique où le client met le
curseur entre le libéralisme et la
rigidité. handling=lenient
signifie que le client
préférerait que le serveur soit libéral, où cas où la requête
contienne quelques erreurs mineures,
handling=strict
, que le client demande au serveur
de n'accepter que des requêtes parfaites.Comme le respect de Prefer:
est facultatif,
attention à ne pas l'utiliser comme substitut de la
négociation de contenu. En effet, il peut être
ignoré par les caches,
qui pourraient mémoriser un contenu correspondant à certaines
préférences et le servir à d'autres clients qui auraient d'autres
préférences. Si le serveur sert des contenus différents selon les
préférences, il doit penser à mettre un Vary:
dans la réponse.
Si le serveur HTTP est sympa, il peut inclure dans la réponse un
en-tête Preference-Applied:
qui indique quelles
préférences ont été effectivement appliquées. Un exemple avec la
commande PATCH
du RFC 5789 et le format du RFC 6902 :
PATCH /my-document HTTP/1.1 Host: example.org Content-Type: application/json-patch Prefer: return=representation [{"op": "add", "path": "/a", "value": 1}]
qui entraîne la réponse :
HTTP/1.1 200 OK Content-Type: application/json Preference-Applied: return=representation Content-Location: /my-document {"a": 1}
Les détails bureaucratiques sont en section 5, consacrée aux
registres IANA. Les en-têtes
Prefer:
et
Preference-Applied:
sont ajoutés au registre
des en-têtes. Un nouveau registre, pour stocker les
préférences, est créé. Les
enregistrements se feront selon la politique « Norme nécessaire » du
RFC 5226 : chaque préférence devra être décrite
dans un document stable, décrivant ses caractéristiques syntaxiques et
sémantiques. Le tout sera envoyé à la liste
ietf-http-wg@w3.org
pour un premier examen, puis
approuvé ou rejeté par l'expert nommé par l'IANA.
Début 2013, il semble que cet en-tête Prefer:
soit déjà géré par Abdera. Le protocole
OData cite aussi cet en-tête. Mais on ne
s'attend pas à ce qu'il soit massivement utilisé par les
navigateurs : il est plutôt prévu pour des
clients automatiques, appelant une API REST.
Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)
Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)