web-dev-qa-db-fra.com

Un corps d'entité est-il autorisé pour une demande HTTP DELETE?

Lors de l'émission d'une requête HTTP DELETE, l'URI de la requête doit identifier complètement la ressource à supprimer. Cependant, est-il permis d'ajouter des méta-données supplémentaires dans le corps d'entité de la demande?

564
Haacked

La spécification ne l'interdit pas explicitement ni ne la décourage, je dirais donc qu'elle est autorisée.

Microsoft le voit de la même manière (j'entends des murmures dans l'audience), comme indiqué dans l'article MSDN sur la méthode DELETE de ADO.NET Data Services Framework :

Si une demande DELETE inclut un corps d'entité, le corps est ignoré [...]

De plus, voici ce que RFC2616 (HTTP 1.1) dit au sujet des demandes:

  • un entity-body n'est présent que lorsqu'un message-body est présent (section 7.2)
  • la présence d'un message-body est signalée par l'inclusion d'un en-tête Content-Length ou Transfer-Encoding (section 4.3)
  • un message-body ne doit pas être inclus lorsque la spécification de la méthode de requête ne permet pas d'envoyer un entity-body (section 4.3)
  • un entity-body est explicitement interdit dans les demandes TRACE uniquement; tous les autres types de demande ne sont soumis à aucune restriction (sections 9 et 9.8 spécifiquement)

Pour les réponses, cela a été défini:

  • l'inclusion d'un message-body dépend à la fois de l'état de la réponse à la méthode de requête et du (section 4.3)
  • un message-body est explicitement interdit dans les réponses aux demandes HEAD (sections 9 et 9.4 en particulier)
  • un message-body est explicitement interdit dans les réponses 1xx (informationnelles), 204 (pas de contenu) et 304 (non modifiées) (section 4.3)
  • toutes les autres réponses incluent un corps de message, même s'il peut avoir une longueur nulle (section 4.3)
467
Tomalak

La dernière mise à jour de la spécification HTTP 1.1 ( RFC 7231 ) autorise explicitement un corps d'entité dans une demande DELETE:

Une charge utile contenue dans un message de demande DELETE n'a pas de sémantique définie; l'envoi d'un corps de données utiles sur une demande DELETE peut amener certaines implémentations existantes à rejeter la demande.

134
grzes

Certaines versions de Tomcat et Jetty semblent ignorer un corps d'entité s'il est présent. Ce qui peut être une nuisance si vous aviez l'intention de le recevoir.

52
evan.leonard

Une des raisons d'utiliser le corps dans une demande de suppression est le contrôle optimiste de la concurrence.

Vous lisez la version 1 d'un enregistrement.

GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }

Votre collègue lit la version 1 du compte rendu.

GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }

Votre collègue modifie l'enregistrement et met à jour la base de données, ce qui met à jour la version 2:

PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }

Vous essayez de supprimer l'enregistrement:

DELETE /some-resource/1 { id:1, version:1 }
409 Conflict

Vous devriez obtenir une exception de verrouillage optimiste. Relisez le compte rendu, voyez qu'il est important, et ne le supprimez peut-être pas.

Une autre raison de l'utiliser consiste à supprimer plusieurs enregistrements à la fois (par exemple, une grille avec des cases à cocher pour la sélection de lignes).

DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content

Notez que chaque message a sa propre version. Peut-être que vous pouvez spécifier plusieurs versions en utilisant plusieurs en-têtes, mais par George, c'est plus simple et beaucoup plus pratique. 

Cela fonctionne dans Tomcat (7.0.52) et Spring MVC (4.05), éventuellement avec des versions antérieures également:

@RestController
public class TestController {

    @RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
    SomeBean echoDelete(@RequestBody SomeBean someBean) {
        return someBean;
    }
}
45
Neil McGuigan

Il me semble que RFC 2616 ne le précise pas.

De la section 4.3:

La présence d'un corps de message dans une requête est signalée par le inclusion d'un champ d'en-tête Content-Length ou Transfer-Encoding dans les en-têtes de la requête. Un corps de message NE DOIT PAS être inclus dans une demande si la spécification de la méthode de la demande (section 5.1.1) n'autorise pas l'envoi d'un corps d'entité dans les requêtes. Un serveur DEVRAIT lire et transférer un corps de message pour toute demande; si la méthode de la demande n'inclut pas la sémantique définie pour un corps d'entité, alors le Le corps du message DEVRAIT être ignoré lors du traitement de la demande.

Et la section 9.7:

La méthode DELETE demande au serveur d'origine de supprimer la ressource identifié par l'URI de la demande. Cette méthode PEUT être remplacée par human intervention (ou autre moyen) sur le serveur Origin. Le client ne peut pas être assuré que l'opération a été effectuée, même si le Le code d'état renvoyé par le serveur d'origine indique que l'action a été complété avec succès. Cependant, le serveur NE DEVRAIT PAS indiquer le succès sauf si, au moment où la réponse est donnée, il a l'intention de supprimer la ressource ou de la déplacer vers un fichier inaccessible emplacement.

Une réponse réussie DEVRAIT être 200 (OK) si la réponse inclut un entité décrivant le statut, 202 (accepté) si l'action n'a pas encore été adopté, ou 204 (pas de contenu) si l'action a été adoptée mais la réponse n'inclut pas une entité.

Si la demande passe par un cache et que l'URL de demande identifie une ou plusieurs entités actuellement mises en cache, ces entrées DEVRAIENT être traité comme rassis. Les réponses à cette méthode ne sont pas cacheable.c

Donc, ce n'est pas explicitement autorisé ou interdit, et il est possible qu'un proxy en cours de route supprime le corps du message (même s'il DEVRAIT le lire et le transférer).

27
Adam Rosenfield

Juste un avertissement, si vous fournissez un corps dans votre demande DELETE et utilisez un équilibreur de charge Google Cloud HTTPS, il rejettera votre demande avec une erreur 400. Je me cognais la tête contre un mur et découvris que pour une raison quelconque, Google considère qu'une requête DELETE avec un corps est une requête mal formée.

14
Ben Fried

Il semble que ElasticSearch utilise ceci: https://www.elastic.co/guide/fr/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api

Ce qui signifie que Netty soutient cela.

Comme mentionné dans les commentaires, il se peut que ce ne soit plus le cas

7
Sebastien Lorber

Ceci n'est pas défini

Une charge utile contenue dans un message de demande DELETE n'a pas de sémantique définie; l'envoi d'un corps de données utiles sur une demande DELETE peut entraîner l'apparition de fichiers implémentations pour rejeter la demande.
https://tools.ietf.org/html/rfc7231#page-29

6
Simon Jin

Il est à noter que la spécification OpenAPI pour la version 3.0 a supprimé la prise en charge des méthodes DELETE avec un corps:

voir ici et ici pour les références

Cela pourrait affecter votre implémentation, la documentation ou l'utilisation de ces API à l'avenir.

5
Clever Human

Si quelqu'un teste ce problème, non, il n'est pas universellement pris en charge.

Je teste actuellement avec Sahi Pro et il est très évident qu'un appel http DELETE supprime toutes les données corporelles fournies (une grande liste d'identifiants à supprimer en bloc, conformément à la conception des terminaux).

Je les ai contactés à plusieurs reprises et leur ai envoyé trois paquets distincts de scripts, d'images et de journaux qu'ils doivent consulter et ils ne l'ont toujours pas confirmé. Un correctif a échoué, et une téléconférence manquée de leur soutien plus tard et je n'ai toujours pas eu de réponse solide.

Je suis certain que Sahi ne supporte pas cela, et j'imagine que de nombreux autres outils suivent.

3
parker

Je ne pense pas qu'une bonne réponse à cela ait été postée, bien qu'il y ait eu beaucoup d'excellents commentaires sur les réponses existantes. Je vais soulever l'essentiel de ces commentaires dans une nouvelle réponse:

Ce paragraphe de RFC7231 a été cité plusieurs fois, ce qui le résume.

Une charge utile contenue dans un message de demande DELETE n'a pas de sémantique définie; l'envoi d'un corps de données utiles sur une demande DELETE peut entraîner le rejet de la demande par certaines implémentations existantes.

Ce qui me manquait des autres réponses était l'implication. Oui, il est permis d'inclure un corps dans les requêtes DELETE, mais cela n'a pas de sens sémantique. Cela signifie réellement qu'émettre une demande DELETE avec un corps de demande équivaut sémantiquement à ne pas inclure un corps de demande.

L'inclusion d'un corps de requête ne devrait avoir aucun effet sur la requête, il est donc inutile de l'inclure.

tl; dr: Techiciquement, une requête DELETE avec un corps de requête est autorisée, mais il n’est jamais utile de le faire.

2
Evert

J'ai pu implémenter l'opération DELETE avec un corps de requête. J'ai utilisé AWS Lambda et la passerelle API AWS, ainsi que le langage Go.

1
Dattatray

Utiliser DELETE avec un corps est risqué ... Je préfère cette approche pour les opérations sur les listes plutôt que sur REST:

Opérations régulières

GET/objects/ Obtient tous les objets

GET/object /ID Obtient un objet avec l'ID spécifié

POST/objects Ajoute un nouvel objet

PUT/object /ID Ajoute un objet avec l'ID spécifié, met à jour un objet

DELETE/object /ID Supprime l'objet avec l'ID spécifié

Toutes les actions personnalisées sont POST

POST/objects / addList Ajoute une liste ou un tableau d'objets inclus dans le corps

POST/objects / deleteList Supprime une liste d'objets inclus dans le corps

POST/objects / customQuery Crée une liste basée sur une requête personnalisée dans le corps

Si un client ne prend pas en charge vos opérations étendues, il peut travailler normalement.

0
Eliezer Garza