Alors que la spécification HTTP 1.1 semble autoriser les corps de message sur les requêtes DELETE , elle semble indiquer que les serveurs devraient l'ignorer car il n'y a pas de sémantique définie pour cela.
4.3 Corps du message
Un serveur DEVRAIT lire et transmettre un corps de message sur toute demande; si la méthode de demande n'inclut pas la sémantique définie pour un corps d'entité, alors le corps de message DEVRAIT être ignoré lors du traitement de la demande.
J'ai déjà passé en revue plusieurs discussions connexes sur ce sujet sur le SO et au-delà, telles que:
- Un corps d'entité est-il autorisé pour une requête HTTP DELETE?
- Charges utiles des méthodes de requête HTTP
- HTTP GET avec le corps de la requête
La plupart des discussions semblent s'accorder sur le fait que fournir un corps de message sur un DELETE peut être autorisé , mais n'est généralement pas recommandé.
De plus, j'ai remarqué une tendance dans diverses bibliothèques clientes HTTP où de plus en plus d'améliorations semblent être enregistrées pour que ces bibliothèques prennent en charge les corps de requête sur DELETE. La plupart des bibliothèques semblent obliger, bien que parfois avec un peu de résistance initiale.
Mon cas d'utilisation demande l'ajout de certaines métadonnées requises sur un DELETE (par exemple, la «raison» de la suppression, ainsi que d'autres métadonnées requises pour la suppression). J'ai examiné les options suivantes, dont aucune ne semble tout à fait appropriée et conforme aux spécifications HTTP et / ou aux meilleures pratiques REST:
- Corps du message - La spécification indique que les corps de message sur DELETE n'ont aucune valeur sémantique; pas entièrement pris en charge par les clients HTTP; pas une pratique courante
- En-têtes HTTP personnalisés - L'exigence d'en-têtes personnalisés est généralement contraire aux pratiques standard ; leur utilisation est incompatible avec le reste de mon API, dont aucune ne nécessite d'en-têtes personnalisés; de plus, aucune bonne réponse HTTP disponible pour indiquer de mauvaises valeurs d'en-tête personnalisées (probablement une question distincte)
- En-têtes HTTP standard - Aucun en-tête standard n'est approprié
- Paramètres de requête - L'ajout de paramètres de requête modifie en fait l'URI de la requête en cours de suppression; contre les pratiques standard
- Méthode POST - (par exemple
POST /resourceToDelete { deletemetadata }
) POST n'est pas une option sémantique pour la suppression; POST représente en fait l' action opposée souhaitée (c'est-à-dire que POST crée des subordonnés de ressources; mais je dois supprimer la ressource) - Méthodes multiples - La division de la demande DELETE en deux opérations (par exemple PUT delete métadonnées, puis DELETE) divise une opération atomique en deux, laissant potentiellement un état incohérent. La raison de la suppression (et les autres métadonnées associées) ne font pas partie de la représentation de la ressource elle-même.
Ma première préférence serait probablement d'utiliser le corps du message, ensuite les en-têtes HTTP personnalisés; cependant, comme indiqué, ces approches présentent certains inconvénients.
Existe-t-il des recommandations ou des meilleures pratiques en ligne avec les normes REST / HTTP pour inclure ces métadonnées requises dans les demandes DELETE? Y a-t-il d'autres alternatives que je n'ai pas envisagées?
la source
Jersey
ne permettent pas le corps desdelete
requêtes.Réponses:
Malgré certaines recommandations de ne pas utiliser le corps du message pour les demandes DELETE, cette approche peut être appropriée dans certains cas d'utilisation. C'est l'approche que nous avons fini par utiliser après avoir évalué les autres options mentionnées dans la question / réponses, et après avoir collaboré avec les consommateurs du service.
Bien que l'utilisation du corps du message ne soit pas idéale, aucune des autres options ne convenait parfaitement non plus. Le corps de la requête DELETE nous a permis d'ajouter facilement et clairement une sémantique autour des données / métadonnées supplémentaires nécessaires pour accompagner l'opération DELETE.
Je serais toujours ouvert à d'autres réflexions et discussions, mais je voulais boucler la boucle sur cette question. J'apprécie les réflexions et les discussions de chacun sur ce sujet!
la source
Ce que vous semblez vouloir est l'une des deux choses, dont aucune n'est pure
DELETE
:PUT
de la raison de la suppression suivie par uneDELETE
de la ressource. Une fois supprimé, le contenu de la ressource n'est plus accessible à personne. La «raison» ne peut pas contenir de lien hypertexte vers la ressource supprimée. Ou,state=active
àstate=deleted
en utilisant laDELETE
méthode. Les ressources avec état = supprimé sont ignorées par votre API principale mais peuvent toujours être lisibles par un administrateur ou une personne ayant accès à la base de données. Ceci est autorisé - ilDELETE
n'est pas nécessaire d'effacer les données de sauvegarde d'une ressource, mais uniquement de supprimer la ressource exposée à cet URI.Toute opération qui nécessite un corps de message sur une
DELETE
requête peut être décomposée en, au plus général, unPOST
pour effectuer toutes les tâches nécessaires avec le corps du message, et aDELETE
. Je ne vois aucune raison de casser la sémantique de HTTP.la source
PUT
raison réussit et que laDELETE
ressource échoue? Comment éviter un état incohérent?Compte tenu de la situation dans laquelle vous vous trouvez, j'adopterais l'une des approches suivantes:
resource/:id
. Vous pouvez le rendre détectable avec des en-têtes de lien sur la ressource pour chaque raison (avec unerel
balise sur chacun pour identifier la raison).resource/:id/canceled
. Cela modifie réellement l'URI de demande et n'est certainement pas RESTful. Encore une fois, les en-têtes de lien peuvent rendre cela détectable.N'oubliez pas que REST n'est ni une loi ni un dogme. Pensez-y davantage comme un guide. Donc, s'il est judicieux de ne pas suivre les instructions pour votre domaine de problème, ne le faites pas. Assurez-vous simplement que vos consommateurs d'API sont informés de l'écart.
la source
/orders/:id
renverrait la même ressource que/orders/:id?exclude=orderdetails
. La chaîne de requête ne donne que des indications au serveur - dans ce cas pour exclure les détails de la commande dans la réponse (si pris en charge). De même, si vous envoyez DELETE à/orders/:id
ou/orders/:id?reason=canceled
ou/orders/:id?reason=bad_credit
, vous agissez toujours sur la même ressource sous-jacente. Pour conserver une «interface uniforme», j'aurais une raison par défaut pour que l'envoi du paramètre de requête ne soit pas nécessaire./foo?123
signifie que vous supprimez une ressource différente de celle si vous deviez envoyer DELETE à/foo?456
.Je vous suggère d'inclure les métadonnées requises dans le cadre de la hiérarchie URI elle-même. Un exemple (naïf):
Si vous devez supprimer des entrées en fonction d'une plage de dates, au lieu de transmettre la date de début et la date de fin dans le corps ou en tant que paramètres de requête, structurez l'URI de manière à transmettre les informations requises dans le cadre de l'URI.
par exemple
DELETE /entries/range/01012012/31122012
- Supprimer toutes les entrées entre le 01 janvier 2012 et le 31 décembre 2012J'espère que cela t'aides.
la source
range
spécifié dans les paramètres de requête ou la charge utile qui est la viande de cette question: pour comprendre l'approche des meilleures pratiques au problème que je dirais n'est pas ceci.