Supprimer une ressource à l'aide de http DELETE

124

Donc, étant donné que le verbe DELETE dans Http est idempotent, lorsque j'émets la requête suivante, que doit-il se passer le deuxième (ou troisième, ou quatrième, etc ...)?

DELETE /person/123

La première fois, la ressource est supprimée et je renvoie un 204 (réussi, pas de contenu). Dois-je renvoyer un 204 lors d'appels ultérieurs ou un 404 (introuvable)?

Craig Wilson
la source

Réponses:

153

Comme les requêtes HTTP dans un système sans état doivent être indépendantes, les résultats d'une requête ne doivent pas dépendre d'une requête précédente. Considérez ce qui devrait se passer si deux utilisateurs effectuaient un DELETE sur la même ressource simultanément. Il est logique que la deuxième demande obtienne un 404. La même chose devrait être vraie si un utilisateur fait deux demandes.

Je suppose qu'avoir DELETE renvoyer deux réponses différentes ne vous semble pas idempotent. Je trouve utile de penser aux demandes idempotentes comme laissant le système dans le même état, sans nécessairement avoir la même réponse. Ainsi, que vous supprimiez une ressource existante ou que vous tentiez de SUPPRIMER une ressource qui n'existe pas, l'état des ressources du serveur est le même.

Darrel Miller
la source
4
Je vous remercie. Cela a tellement de sens. Je pensais en effet à idempotent comme renvoyant la même réponse.
Craig Wilson
4
@Craig Attention! Dans le livre de cuisine, Subbu contredit complètement ce que je viens de dire. Il dit que l'idempotence signifie qu'elle devrait renvoyer la même réponse. Heureusement, Subbu va être au RESTFest alors je vais clarifier avec lui là-bas.
Darrel Miller
58
Si vous SUPPRIMEZ quelque chose qui n'existe pas, vous devez simplement renvoyer un 204 (même si la ressource n'a jamais existé). Le client voulait que la ressource disparaisse et elle est partie. Le retour d'un 404 expose un traitement interne qui n'est pas important pour le client et entraînera une condition d'erreur inutile.
Brian
9
@DarrelMiller Je suppose que le concept clé ici est que vous ne devriez pas utiliser DELETE pour vérifier si une ressource existe, vous utiliseriez d'abord GET pour cela. Ensuite, si la réponse est 200, vous effectuerez un DELETE; sinon, ne prenez même pas la peine de faire ça. Je pense donc qu'il est logique de toujours renvoyer un 204 sur DELETE.
manei_cc
10
@Brian Le RFC dit qu'il est censé se comporter comme rm. rmrenvoie une erreur si elle n'existe pas. tools.ietf.org/html/rfc7231#section-4.3.5
Dax Fohl
32

Le livre de recettes des services Web RESTful est une excellente ressource pour cela. Par chance, son aperçu google affiche la page sur DELETE (page 11):

La méthode DELETE est idempotente. Cela implique que le serveur doit renvoyer le code de réponse 200 (OK) même si le serveur a supprimé la ressource dans une requête précédente. Mais en pratique, la mise en œuvre de DELETE en tant qu'opération idempotente nécessite que le serveur garde une trace de toutes les ressources supprimées. Sinon, il peut renvoyer un 404 (non trouvé).

Yves Amsellem
la source
Oui, cela ressemble à une excellente ressource. Cependant, la section DELETE ne tire pas vers le haut pour moi (c'est la page 23 et l'aperçu l'a expurgée). As tu lu ce livre? Connaissez-vous la réponse à ma question?
Craig Wilson
Ce livre est un must pour construire REST (il parle en particulier, pas dans une langue).
yves amsellem
7
@Craig En lisant le livre de recettes, il est dit que vous DEVRIEZ renvoyer 200 OK même si vous l'avez déjà supprimé. Cependant, dans la pratique, cela exigerait que le serveur suive toutes les ressources supprimées, par conséquent, vous POUVEZ utiliser 404. Il continue en disant que les problèmes de sécurité peuvent vous obliger à toujours renvoyer 404. Page 11.
Darrel Miller
+1 seconde et recommande vivement le livre pour la conception de services RESTful.
Paul DelRe
18
Eh bien, le livre est faux. L'idempotence n'implique pas que le code d'état sera le même. Ce qui est pertinent, c'est l'état final du serveur.
Julian Reschke
13

Je suis d'accord avec ce que la réponse choisie actuelle a dit, que le 2e (et 3e, 4e, ...) SUPPRIMER devrait obtenir un 404 . Et, j'ai remarqué que la réponse avait 143 votes positifs, mais aussi un commentaire opposé qui a 54 votes positifs, de sorte que la communauté est divisée en 2 camps dans un rapport d'environ 3: 1. Voici plus d'informations pour régler ce débat de longue date.

  1. Tout d'abord, ne commençons PAS par ce que «je» pense, ce que «vous» pensez ou ce qu'un autre auteur de livre pense. Commençons par les spécifications HTTP, c'est-à-dire RFC 7231.

    • La RFC 7231, section 4.3.5 DELETE est arrivée à mentionner seulement qu'une réponse réussie devrait être 2xx, mais elle n'a pas appelé ce qu'un DELETE ultérieur obtiendrait. Alors creusons plus profondément.
    • RFC 7231, section 6.5.4 404 Not Found indique que la réponse 404 est pour une ressource n'existe pas. Puisqu'aucune méthode http spécifique (en particulier, pas DELETE) n'est appelée pour être traitée autrement, nous pouvons intuitivement avoir l'impression (et à juste titre), que ma requête DELETE /some/resource/which/does/not/existdevrait aboutir à un 404. Ensuite, DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/agopourrait aussi bien renvoyer un 404 Alors, pourquoi devrait-il DELETE /some/resource/i/deleted/five/seconds/agoêtre différent? "Mais qu'en est-il de l'idempotence?!", Je peux vous entendre crier ça. Attendez, nous sommes sur le point d'entrer dans cela.
    • Historiquement, la RFC 2616, publiée en 1999, était la spécification HTTP 1.1 la plus référencée. Malheureusement sa description de l'idempotence était vague , ce qui laisse place à tous ces débats. Mais cette spécification a été remplacée par la RFC 7231. Cité de la RFC 7231, section 4.2.2 Méthodes idempotentes , je souligne:

      Une méthode de demande est considérée comme "idempotente" si l'EFFET prévu SUR LE SERVEUR de plusieurs demandes identiques avec cette méthode est le même que l'effet pour une seule demande de ce type. Parmi les méthodes de demande définies par cette spécification, les méthodes de demande PUT, DELETE et sûres sont idempotentes .

      Donc, il est écrit dans les spécifications, l'idempotence est une question d'effet sur le serveur. Le premier DELETE renvoyant un 204 puis DELETE ultérieur renvoyant 404, un tel code d'état différent ne rend PAS le DELETE non idempotent. Utiliser cet argument pour justifier un retour 204 ultérieur n'est tout simplement pas pertinent.

  2. OK donc il ne s'agit pas d'idempotence. Mais alors une question de suivi peut être, que se passe-t-il si nous choisissons toujours d'utiliser 204 dans DELETE ultérieur? Est-ce que c'est bon?

    Bonne question. La motivation est compréhensible: permettre au client d'atteindre le résultat souhaité, sans se soucier de la gestion des erreurs. Je dirais que renvoyer 204 dans DELETE subséquent est un "mensonge blanc" côté serveur largement inoffensif, dont le côté client ne fera pas immédiatement la différence. C'est pourquoi il y a environ 25% de personnes qui font cela dans la nature et cela fonctionne toujours. Gardez simplement à l'esprit qu'un tel mensonge peut être considéré comme sémantiquement bizarre, car GET /non-existrenvoie 404 mais DELETE /non-existdonne 204, à ce moment-là, le client comprendra que votre service n'est pas entièrement conforme à la section 6.5.4 404 Not Found .

    Mais je tiens à souligner que, la manière prévue suggérée par RFC 7231, c'est-à-dire renvoyer 404 lors de DELETE ultérieur, ne devrait pas être un problème en premier lieu. 3 fois plus de développeurs ont choisi de le faire, et avez-vous déjà entendu un incident majeur ou une plainte causée par un client incapable de gérer 404? Vraisemblablement, non, et c'est parce que tout client décent qui implémente HTTP DELETE (ou toute méthode HTTP, d'ailleurs), ne supposerait pas aveuglément que le résultat serait toujours réussi 2xx. Et puis, une fois que le développeur commence à envisager la gestion des erreurs, 404 Not Found serait l'une des premières erreurs qui viendraient à l'esprit. À ce stade, il / elle tirerait probablement une conclusion selon laquelle il est sémantiquement sûr pour une opération HTTP DELETE d'ignorer une erreur 404. Et ils l'ont fait.

Problème résolu.

RayLuo
la source
2
+1 "L'idempotence est une question d'effet sur le serveur". Répondit méticuleusement. Bien joué! Je suis un partisan 404 pour les demandes DELETE ultérieures.
nwayve le
11

Premier SUPPRIMER : 200 ou 204.

SUPPRESSIONS suivantes : 200 ou 204.

Justification : DELETE doit être idempotent. Si vous renvoyez 404 sur un deuxième SUPPRIMER, votre réponse passe d'un code de réussite à un code d'erreur . Le programme client peut prendre des actions incorrectes en fonction de l'hypothèse que la suppression a échoué.

Exemple :

  • Supposons que votre opération DELETE fasse partie d'une opération en plusieurs étapes (ou d'une "saga") exécutée par le programme client.
  • Le programme client peut être une application mobile effectuant une transaction bancaire, par exemple.
  • Disons que le programme client a une nouvelle tentative automatique pour une opération DELETE (cela a du sens, car DELETE est supposé être idempotent).
  • Disons que le premier DELETE a été exécuté avec succès, mais que la réponse 200 s'est perdue sur son chemin vers le programme client.
  • Le programme client essaiera de nouveau DELETE.
  • Si la deuxième tentative renvoie 404, le programme client peut annuler l'opération globale en raison de ce code d'erreur.
  • Mais comme le premier DELETE exécuté avec succès sur le serveur, le système peut être laissé dans un état incohérent .
  • Si la deuxième tentative renvoie 200 ou 204, le programme client continuera comme prévu.

Juste pour illustrer l'utilisation de cette approche, le guide de style de l'API HTTP pour PayPal a la directive suivante:

DELETE: Cette méthode DEVRAIT renvoyer le code d'état 204 car il n'est pas nécessaire de renvoyer de contenu dans la plupart des cas car la demande consiste à supprimer une ressource et qu'elle a été supprimée avec succès.

Comme la méthode DELETE DOIT également être idempotente, elle DEVRAIT toujours retourner 204, même si la ressource a déjà été supprimée. En général, le consommateur d'API ne se soucie pas de savoir si la ressource a été supprimée dans le cadre de cette opération ou avant. C'est aussi la raison pour laquelle 204 au lieu de 404 doivent être renvoyés.

Paulo Merson
la source
1
La question est de savoir ce qui est important pour le client, qu'il a supprimé la ressource ou que la ressource a été supprimée. Et si un autre client supprimait la ressource pendant la saga. Voulez-vous vraiment échouer compte tenu de l'atteinte de l'objectif client?
Darrel Miller
1
@DarrelMiller Bon point. Ce qui est le plus important dépend du contexte commercial. Mais en général, je préfère retourner 204 sur une deuxième tentative DELETE, même si la ressource a été supprimée par un autre client. Je ne veux pas que le service échoue (c'est-à-dire 404) étant donné que l'objectif du client a été atteint.
Paulo Merson
2
Comme d'autres l'ont mentionné, l'idempotence n'est pas ce qu'est votre code de réponse, c'est l'état de votre serveur.
Niranjan
@Niranjan Je suis d'accord que l'idempotence concerne l'état du serveur, mais un code de réponse différent peut conduire le client à changer l'état du serveur inutilement en annulant une saga en cours.
Paulo Merson
@Paulo Merson quel code retournerez-vous si le client demande la suppression d'un élément qui n'a JAMAIS existé? 204? ou 404? Si vous renvoyez toujours 204, quel est l'intérêt de vérifier le code de retour?
frenchone