REST, HTTP DELETE et paramètres

135

Y a-t-il quelque chose de non-RESTful à propos de la fourniture de paramètres à une requête HTTP DELETE?


Mon scénario est que je modélise le "Êtes-vous sûr de vouloir supprimer cela?" scénario. Dans certains cas, l'état de la ressource suggère que la suppression demandée peut être invalide. Vous pouvez probablement imaginer vous-même certains scénarios où la confirmation d'une suppression est requise

La solution que nous avons adoptée est de passer un paramètre à la demande de suppression pour indiquer que vous pouvez procéder à la suppression ("? Force_delete = true")

par exemple

DELETE http://server/resource/id?force_delete=true

Je crois que c'est toujours reposant depuis:

(a) La sémantique de DELETE n'est pas modifiée - l'utilisateur peut toujours envoyer une demande DELETE normale mais cela peut échouer avec 409 et le corps de la réponse expliquera pourquoi. Je dis peut échouer parce que (pour des raisons qui ne valent pas la peine d'être expliquées) à certaines occasions, il n'y a aucune raison d'inviter l'utilisateur.

(b) Il n'y a rien dans la thèse de Roy qui suggère que c'est contre l'esprit de REST - pourquoi y en aurait-il puisque HTTP n'est qu'une implémentation de REST alors pourquoi le passage des paramètres HTTP serait-il important?


Quelqu'un peut-il m'indiquer une déclaration définitive qui explique pourquoi ce n'est pas RESTful?

Sur une question connexe, si l'utilisateur ne spécifie pas force_delete, je retourne 409 Conflict- est-ce le code de réponse le plus approprié?


Suivre

Après quelques recherches supplémentaires, je pense que l'ajout de paramètres à DELETE peut enfreindre plusieurs principes.

La première est que l'implémentation viole peut-être l '«interface uniforme» (voir section 5.1.5 de la thèse de Roy

En ajoutant «force_delete», nous ajoutons une contrainte supplémentaire sur la méthode DELETE déjà bien définie. Cette contrainte n'a de sens que pour nous.

Vous pouvez également affirmer que cela enfreint le "5.1.2 Client-Serveur" car le dialogue de confirmation est vraiment un problème d'interface utilisateur et encore une fois, tous les clients ne voudront pas confirmer la suppression.

Suggestions quelqu'un?

Chris McCauley
la source
1
Votre URL pour la thèse de Roy contient un ")" qui provoque un 404. ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm fonctionne.
NuclearPeon

Réponses:

78

Non, ce n'est pas RESTful. La seule raison pour laquelle vous devriez mettre un verb ( force_delete) dans l'URI est si vous devez surcharger les méthodes GET / POST dans un environnement où les méthodes PUT / DELETE ne sont pas disponibles. À en juger par votre utilisation de la méthode DELETE, ce n'est pas le cas.

Le code d'erreur HTTP 409/Conflictdoit être utilisé dans les situations où il y a un conflit qui empêche le service RESTful d'effectuer l'opération, mais il y a encore une chance que l'utilisateur puisse résoudre le conflit lui-même. Une confirmation de pré-suppression (où il n'y a pas de conflits réels qui empêcheraient la suppression) n'est pas un conflit en soi, car rien n'empêche l'API d'effectuer l'opération demandée.

Comme l'a dit Alex (je ne sais pas qui a voté contre lui, il a raison), cela devrait être géré dans l'interface utilisateur, car un service RESTful en tant que tel ne traite que les demandes et devrait donc être apatride (c'est-à-dire qu'il ne doit pas s'appuyer sur des confirmations en tenant toute information côté serveur sur une requête).

Deux exemples de procédure dans l'interface utilisateur seraient les suivants:

  • pré-HTML5 : * afficher une boîte de dialogue de confirmation JS à l'utilisateur et envoyer la demande uniquement si l'utilisateur la confirme
  • HTML5 : * utiliser un formulaire avec l'action DELETE où le formulaire ne contiendrait que les boutons "Confirmer" et "Annuler" ("Confirmer" serait le bouton d'envoi)

(*) Veuillez noter que les versions HTML antérieures à 5 ne prennent pas en charge les méthodes HTTP PUT et DELETE de manière native, cependant la plupart des navigateurs modernes peuvent utiliser ces deux méthodes via des appels AJAX. Consultez ce fil pour plus de détails sur la prise en charge de plusieurs navigateurs.


Mise à jour (basée sur une enquête et des discussions supplémentaires):

Le scénario où le service exigerait que le force_delete=truedrapeau soit présent viole l' interface uniforme telle que définie dans la thèse de Roy Fielding. De plus, selon HTTP RFC , la méthode DELETE peut être remplacée sur le serveur d'origine (client), ce qui implique que cela n'est pas fait sur le serveur cible (service).

Ainsi, une fois que le service reçoit une demande DELETE, il doit la traiter sans avoir besoin de confirmation supplémentaire (peu importe si le service effectue réellement l'opération).

MicE
la source
2
Pouvez-vous expliquer quelle contrainte REST est violée? Considérant que les URI doivent être opaques pour le client, pourquoi pensez-vous que les attentes du client ne sont pas satisfaites avec l'utilisation d'un HTTP DELETE qui supprime une ressource mais ne parvient pas à en supprimer une autre. Je ne suis pas sûr que 409 soit le meilleur code de statut à renvoyer, mais en plus d'être une implémentation un peu étrange, je ne trouve aucune contrainte REST en cours de rupture.
Darrel Miller
2
@Darrel: (à mon humble avis) il viole l'interface uniforme par la méthode DELETE ne fonctionnant pas selon les normes HTTP. Considérez un client REST qui suppose un service REST standard - comment le service fera-t-il savoir au client qu'il doit ajouter force_delete=true? Selon HTTP RFC, la méthode DELETE peut être remplacée sur le serveur d'origine (client), ce qui implique que cela n'est pas fait sur le serveur cible (service). Donc, je crois comprendre qu'une fois que le service reçoit une demande DELETE, il doit la traiter sans avoir besoin de confirmation (que le service effectue réellement l'opération).
MicE
1
@Chris, à votre deuxième point: oui, c'est aussi ce que je comprends, c'est-à-dire que l'État suggère un vrai conflit et non un besoin de confirmation. Je viens de remarquer la mise à jour que vous avez faite dans votre question, et je suis d'accord - pendant que je la regardais moi-même, je suis arrivé à la même conclusion (que cela viole l'interface uniforme, et que la confirmation doit être faite sur le client / l'interface utilisateur côté). J'ai également rencontré un fil de discussion très intéressant ici, cela pourrait aider: mail-archive.com/[email protected]/msg13578.html
MicE
2
@MicE Dans une large mesure, je suis d'accord avec vous pour dire que ce n'est pas la manière idéale de gérer ce scénario. Je suis juste un peu pointilleux à propos du label "ce n'est pas RESTful". Pendant un moment, cette phrase a été lancée sur tout. Cependant, il serait possible de définir des règles pour un type de média qui disent que si vous essayez de SUPPRIMER une ressource et que vous obtenez une erreur (je dirais que 403 interdit serait mieux que 409), alors le client devrait tenter DELETE sur une ressource associée en clouant sur un "force_delete = true". D'une certaine manière, c'est un peu comme une autorisation. Faites GET, obtenez 401, ajoutez l'en-tête d'authentification et GET à nouveau.
Darrel Miller
2
@Darrel: c'est un très bon point, merci. Et j'ai vu des gens lancer moi-même l'étiquette non RESTful . Il se peut que de nos jours, la barrière entre les services et les applications Web devienne très brumeuse, de sorte qu'un groupe de personnes peut voir cela d'un point de vue purement service, tandis que d'autres le voient d'un point de vue mixte application / service. C'est, je crois, que la vraie question sur la façon de faire la confirmation entre en jeu. @Chris: mis à jour - merci monsieur pour un sujet et une discussion très intéressants!
MicE
35

Je pense que ce n'est pas reposant. Je ne pense pas que le service de repos devrait gérer l'exigence de forcer l'utilisateur à confirmer une suppression. Je gérerais cela dans l'interface utilisateur.

La spécification de force_delete = true a-t-elle un sens s'il s'agissait de l'API d'un programme? Si quelqu'un écrivait un script pour supprimer cette ressource, voudriez-vous le forcer à spécifier force_delete = true pour supprimer réellement la ressource?

Alex Rockwell
la source
Le premier paragraphe de votre réponse est votre opinion et je respecte cela, mais vous n'avez pas signalé quelque chose dans la littérature qui interdit l'utilisation de l'URI comme ceci - il identifie toujours la ressource et le verbe HTTP le plus approprié est utilisé. En réponse à vos questions; oui ça aurait encore du sens (à mon avis). Je m'attendrais à ce qu'un script (peut-être basé sur CURL) respecte la réponse 409 et suggère à l'utilisateur comment la demande pourrait être renvoyée - le tout basé sur mon corps de réponse
Chris McCauley
Bon point sur la comparaison de l'API Web à l'API d'un programme. C'est souvent un bon moyen de savoir si une API est RESTful ou non.
laurent
18

C'est une vieille question, mais voici quelques commentaires ...

  1. En SQL, la commande DELETE accepte un paramètre "CASCADE", qui vous permet de spécifier que les objets dépendants doivent également être supprimés. Ceci est un exemple de paramètre DELETE qui a du sens, mais 'man rm' pourrait en fournir d'autres. Comment ces cas pourraient-ils être implémentés dans REST / HTTP sans paramètre?
  2. @Jan, il semble être une convention bien établie selon laquelle la partie chemin de l'URL identifie une ressource, alors que la chaîne de requête ne le fait pas (du moins pas nécessairement). Les exemples abondent: obtenir la même ressource mais dans un format différent, obtenir des champs spécifiques d'une ressource, etc. Si l'on considère la chaîne de requête comme faisant partie de l'identifiant de la ressource, il est impossible d'avoir un concept de «vues différentes de la même ressource» sans recourir à des mécanismes non REST tels que la négociation de contenu HTTP (ce qui peut être indésirable pour de nombreuses raisons).
Shay Rojansky
la source
Merci d'avoir ajouté cela à la conversation, même si ce n'est pas vraiment une conversation car cela dure des années.
silviot
6

En plus de la réponse d'Alex:

Notez que http: // serveur / ressource / id? Force_delete = true identifie une ressource différente de http: // serveur / ressource / id . Par exemple, il y a une énorme différence que vous supprimiez / clients /? Status = old ou / customers /.

Jan

Jan Algermissen
la source
Je ne suis pas d'accord, je suis libre de fournir plusieurs URI pour identifier la même ressource.
Chris McCauley
19
Oui - tout le monde est libre de faire un gâchis :-)
Jan Algermissen
L'indication des URI canoniques pourrait aider avec ceci: googlewebmastercentral.blogspot.com/2009/02/…
MicE
@Chris Il ne doit y avoir qu'un seul URI qui renvoie une représentation d'une ressource. D'autres URI peuvent faire référence au même concept mais faire un GET devrait renvoyer un 303 See Other. Et juste pour contrer l'objection évidente à cela, /foo.xml et /foo.json sont deux ressources différentes.
Darrel Miller
@Darrell - d'accord mais le format n'est pas un problème ici. Le .format est également une convention dans Rails et d'autres frameworks ne faisant pas partie de REST - vous devriez utiliser la négociation de contenu en HTTP avec MIME ou des microformats pour l'implémenter pleinement.
Chris McCauley