Bref rappel des méthodes HTTP
Pour rappel, voici les principaux verbes HTTP que nous utilisons pour des architectures REST :
- GET : Accède à une ressource
- HEAD : Accède aux métadonnées d’une ressource
- POST : Ajoute une ressource
- PUT : Met à jour une ressource complète en la remplaçant par une nouvelle version (99% des cas).
- PATCH : Met à jour une partie d’une ressource en envoyant un différentiel (une sorte de ‘git diff’)
- DELETE : Supprime une ressource
Méthodes safes (sûres) et idempotents (idempotentes)
La RFC7231 (remplaçante de la RFC2616) a ajouté deux notions aux méthodes HTTP :
- Les méthodes dites safes ne modifient pas les données sur le serveur. Peu importe le nombre de fois qu’elles sont appelées.
- Les méthodes idempotents quant à elles peuvent modifier les données lors du premier appel. Lors des appels suivants, la réponse sera tout le temps identique. En cas de panne/problème réseau, vous pourrez donc lancer la requête sans craintes puisque le comportement est le même que vous exécutiez la requête une ou plusieurs fois.
Méthode | Safe | Idempotente GET | Oui | Oui HEAD | Oui | Oui POST | Non | Non PUT | Non | Oui PATCH | Non | Non DELETE | Non | Oui
Focus sur le DELETE : On serait tenté de dire que DELETE n’est pas idempotent car on ne peut pas supprimer deux fois le même objet. Ceci étant, si l’on regarde la RFC, DELETE doit bien retourner un code 200 (Success) en cas de réussite et non pas un 204 (No Content). Si l’API n’a pas été bien conçue et qu’elle renvoie un 404 (Not Found), alors le DELETE ne sera plus idempotent comme elle devrait l’être.
Cachabilité
“La requête la plus performante est celle que l’on a pas à faire !”
— Un inconnu
La mise en cache est l’une des contraintes les plus importantes des architectures web. En effet, elle permet de :
- décharger votre serveur en lui évitant de refaire la même chose deux fois,
- réduire le temps de traitement d’une requête,
- …et donc de renvoyer plus rapidement l’information au client.
Les méthodes dites safes sont donc à mettre en cache !
Bonnes/mauvaises pratiques
Il y a malheureusement, trop d’API conçue comme ceci :
Ce sont de mauvaises pratiques liées à une mauvaise compréhension des verbes HTTP. Quand il y a un
nom d’action CRUD dans l’URI c’est qu’il y a un problème. De plus, dans la partie précédente, je
parle de cachabilité. Si vous faites une recherche avec POST, le serveur n’utilisera pas le cache…
mais il le mettra peut-être à jour (pour d’éventuels GET à venir qui ne viendront jamais).
Si vous utilisez un POST au lieu d’un PUT (ou autre méthode idempotent) et que par mégarde, vous
exécutez cet appel plusieurs fois, il peut y avoir des effets de bords non désirés.
Création POST vs. PUT
Lors d’une création de ressource, il y a deux cas de figure : le serveur a la main sur la génération de l’id (ou du nom de la ressource) ou bien le cas contraire. Dans le premier cas, il faut privilégier le POST et dans l’autre le PUT. En d’autres termes, n’utilisez PUT pour la création uniquement si c’est au client connait l’URI de la ressource à créer.
Exemple avec les ressources subordonnées.
Nous avons une ressource comme celle ci-dessus et que nous voulons ajouter un ingrédient. Il pourrait-être tentant de faire un PUT sur la ressource entière. Pourtant un ingrédient est… aussi une ressource ! Il faudra donc faire :
En effet, ici POST pas possible car un ingrédient peut se retrouver dans plusieurs pizzas. Dans le cas contraire, un POST aurait été utilisé comme ceci :
Le cas des modifications partielles
Si on regarde le panel de méthodes HTTP, on voit qu’il y a deux méthodes pour modifier une ressource : PUT et PATCH. Si vous vous souvenez bien GET requière une ressource entière et PATCH effectue un différentiel (avec les anciennes données). Donc dans les deux cas vous êtes obligés de faire un GET avant.
Là, je vous vois venir :
“On a qu’à faire un PUT partiel et puis c’est tout !”
Et bien non ! Comme le dit si bien le papa de REST, un PUT partiel n’est pas compatible avec une API RESTful. Par extension, il en va de même pour le POST partiel.
@mnot Oy, yes, PATCH was something I created for the initial HTTP/1.1 proposal because partial PUT is never RESTful. ;-)
— Roy T. Fielding (@fielding) 3 Décembre 2012
Bref, c’est toujours le même problème qui revient : Théorie Vs. Pragmatisme :
- Soit vous collez à fond à la spec HTTP pour avoir une vrai API REST et utilisez PATCH ;
- Soit vous oubliez avoir lu cet article et continuez d’utiliser un POST/PUT partiel. Mais votre API ne sera pas pleinement REST ;-)
Sortir du cadre CRUD
Même si ce n’est pas l’objet de cet article, je vais tout de même en parler un peu, car contrairement à ce que certains pensent, il est possible de sortir du cadre CRUD avec une API REST. Vous devrez alors utiliser la méthode POST, et ainsi profiter du caractère unsafe/non-idempotent de cette dernière. Utiliser POST vous protège d’effets de bord évoqués précédemment (ex : retirer deux fois l’argent sur le compte d’un client, double envoi de mail, …).
Exemple : POST api.mon-application.org/utilisateurs/42/envoyer-mail-confirmation
N’oubliez pas que c’est un échange entre le client et le serveur. Par conséquent, il doit y avoir une réponse. Réponse qui se matérialise dans le cas présent par des codes. Dans le cas présent, il faudra renvoyer un 204 No Content.
Sources
- Si vous voulez en savoir plus sur l’utilisation de PATCH, je vous recommande cet article : blog de William DURAND - Please do not PATCH like an idiot dédié à ce sujet.
- J’ai récement découvert cet ouvrage : REST API Design Rulebook (Mark Masse). C’est une véritable mine d’or. Si vous vous posez des questions du type : quel code HTTP retourner ? Quelle forme d’URL est la plus judicieuse ? Ai-je le droit de faire xxx ? … ce livre est fait pour vous !
- Enfin, le restcookbook et l’article de Jason Sirota : REST Partial Updates: Use POST, PUT or PATCH? m’ont beaucoup aidé.
About the author
Hey, I'm Maxence Poutord, a passionate software engineer. In my day-to-day job, I'm working as a senior front-end engineer at Orderfox. When I'm not working, you can find me travelling the world or cooking.
Follow me on Bluesky