Date de publication du RFC : Mars 2010
Auteur(s) du RFC : L. Dusseault (Linden Labs), J. Snell
Chemin des normes
Première rédaction de cet article le 19 mars 2010
Le célébrissime protocole HTTP (décrit dans
le RFC 7230 et suivants) prévoit plusieurs
méthodes pour interagir avec une
ressource, identifiée par un
URI. Dans le cas le plus connu, la ressource
est une page en HTML et la méthode utilisée est
GET, pour récupérer ladite page. Mais HTTP
dispose d'autres méthodes, comme PUT ou
DELETE. Ce RFC 5789 ajoute à la
liste une méthode de modification partielle d'une ressource,
PATCH.
Si GET sert à récupérer une ressource (par
exemple un fichier), DELETE à détruire une
ressource, et PUT à installer une nouvelle
version toute neuve, PATCH permettra de modifier
une ressource sans envoyer l'intégralité de la nouvelle
ressource. L'intérêt principal est de transmettre des mises à jour de
petite taille, au lieu de renvoyer une (peut-être très grosse)
ressource complète. Pour l'instant, je ne connais pas de mise en œuvre
disponible officiellement (voir à la fin de cet article pour quelques idées).
Il faut noter tout de suite que le format de la modification envoyée n'est pas spécifié : plusieurs formats seront possible, le client HTTP devra indiquer le format utilisé et espérer que le serveur l'accepte.
Pourquoi ne pas utiliser les méthodes existantes au lieu d'inventer
PATCH ? La section 1 répond à cette
question. PUT remplace complètement la ressource
(et utiliser PUT pour envoyer une modification
partielle, même si le serveur final comprend l'opération, sémerait la
confusion chez les relais) et
POST est trop mal spécifié (il sert un peu de
méthode fourre-tout).
La nouvelle méthode est décrite en détail en section 2. Le client
envoie le patch et indique
l'URI de la ressource auquel il s'applique. Le
patch est une série d'instructions indiquant
comment modifier l'ancienne ressource pour atteindre l'objectif, la
nouvelle ressource. Il existe plusieurs langages pour de telles
instructions comme les patches
XML du RFC 5261, comme le
langage de patch traditionnel des
programmeurs (type non officiel
text/x-diff), etc. Au fur et à mesure de leur
définition officielle, ces types seront enregistrés dans le registre.
Attention, comme rappelé à plusieurs reprises dans le RFC,
PATCH n'est pas
idempotent (pas plus que
POST, voir le RFC 7231,
section 9.1.2). La question a été vigoureusement
discutée à l'IETF lors de l'élaboration de ce
RFC et la conclusion générale était qu'assurer une telle sémantique
serait très coûteux et pas toujours nécessaire.
De même, PATCH ne garantit pas forcément l'état final de
la ressource : avec certains langages de
patch, un patch, appliqué à une
version différente de la ressource, peut engendrer des résultats
inattendus (contrairement à PUT). C'est au client HTTP de s'assurer qu'il utilise bien la
bonne version de la ressource. Comment ? Le plus simple est que le
client demande un Etag (RFC 7232, section 2.3) par un GET,
calcule les changements, avant
d'envoyer le PATCH accompagné d'un en-tête
If-Match: (RFC 7232,
section 3.1). Ainsi, le client sera sûr de partir d'un état connu de
la ressource. Cette méthode résout également le cas de deux clients
tentant de patcher à peu près
simultanément. (L'en-tête If-Unmodified-Since: est
une alternative passable à If-Match:.) Avec
certains langages de patch, ou bien pour certaines
opérations (par exemple ajouter une ligne à la fin d'un
journal), ces précautions ne sont pas
nécessaires.
En revanche, PATCH garantit
l'atomicité. La ressource sera complètement
modifiée ou pas du tout (le logiciel patch
d'Unix ne garantit pas cela).
PATCH ne permet de changer que le contenu de
la ressource, pas ses métadonnées. Si la requête
PATCH a des en-têtes, ils décrivent la requête,
pas la ressource et des attributs comme le type
MIME ne peuvent donc pas
être modifiés via PATCH.
HTTP permet de traverser des caches et
ceux-ci devraient évidemment invalider une ressource pour laquelle un
PATCH est passé.
Voici l'exemple de PATCH de la section 2.1,
utilisant un langage de patch imaginaire, indiquée
par le type MIME application/example :
PATCH /file.txt HTTP/1.1 Host: www.example.com Content-Type: application/example If-Match: "e0023aa4e" Content-Length: 100 [Le patch, au format "application/example"]
Et son résultat (rappel : 204 indique un succès mais où la ressource n'est pas renvoyée, contrairement à 200) :
HTTP/1.1 204 No Content Content-Location: /file.txt ETag: "e0023aa4f"
Et si ça se passe mal ? La section 2.2 décrit les cas d'erreur possibles parmi lesquels :
If-Match:, ce qui
est le cas si un autre processus a modifié la ressource entre temps :
409 ou 412 selon le cas,Pour interagir proprement avec les clients et les serveurs HTTP qui
ne connaissent pas PATCH, la section 3 décrit
l'information qu'on peut envoyer en réponse à la commande
OPTIONS, pour indiquer qu'on accepte
PATCH :
OPTIONS /example/buddies.xml HTTP/1.1 Host: www.example.com [La réponse] HTTP/1.1 200 OK Allow: GET, PUT, POST, OPTIONS, HEAD, DELETE, PATCH Accept-Patch: application/example, text/example
D'autre part, le nouvel en-tête
Accept-Patch: (section 3.1 et 4.1 pour le registre IANA) sert à préciser les
formats de patch acceptés.
Comme PATCH modifie une ressource Web, il
n'est pas étonnant que la section de ce RFC 5789 sur la
sécurité soit assez détaillée. Plusieurs
problèmes peuvent se poser :
PUT concernant
l'autorisation de l'utilisateur à modifier la
ressource. A priori, PATCH ne sera pas ouvert au
public et nécessitera une
authentification.PUT) qui peut être traité par
les techniques de requêtes conditionnelles
(If-Match:...).PUT ou POST la présence de
contenus à problèmes, par exemple un
virus. PATCH permettrait
de contourner ces contrôles en envoyant le contenu en plusieurs
fois. Mais le problème n'est pas très différent de celui posé par les
contenus envoyés en plusieurs fois avec Content-Range: (le RFC cite aussi le cas des contenus comprimés, ce que je trouve moins
convaincant).Pour implémenter PATCH, quelques idées :
Un autre article en français sur cette technologie : http://pierre.dureau.me/billet/2011-04-06-http-patch.
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)