Si une opération RESTful 'PUT' renvoie quelque chose

437

Je me demandais ce que les gens pensent d'une PUTopération RESTful qui ne renvoie rien (nul) dans le corps de la réponse.

AwkwardCoder
la source

Réponses:

615

La spécification HTTP ( RFC 2616 ) contient un certain nombre de recommandations applicables. Voici mon interprétation:

  • Code d'état HTTP 200 OKpour un PUT réussi d'une mise à jour d'une ressource existante. Aucun organisme d'intervention n'est nécessaire. (Selon la section 9.6 , 204 No Contentc'est encore plus approprié.)
  • Code d'état HTTP 201 Createdpour un PUT réussi d'une nouvelle ressource, avec l'URI le plus spécifique pour la nouvelle ressource retourné dans le champ d'en-tête Location et tout autre URI et métadonnées de la ressource en écho dans le corps de la réponse. ( RFC 2616 section 10.2.2 )
  • Code d'état HTTP 409 Conflictpour un PUT qui échoue en raison d'une modification à une troisième partie, avec une liste des différences entre la tentative de mise à jour et la ressource actuelle dans le corps de la réponse. ( RFC 2616 Section 10.4.10 )
  • Code d'état HTTP 400 Bad Requestpour un PUT non réussi, avec du texte en langage naturel (tel que l'anglais) dans le corps de la réponse qui explique pourquoi le PUT a échoué. ( RFC 2616 Section 10.4 )
système PAUSE
la source
25
@stian Intéressant! Cela semble assez présomptueux de la part de Mozilla, car je ne trouve rien dans la RFC 2616 (notamment les sections 10.2 Successful 2xx et 10.2.1 200 OK ) qui exclut spécifiquement l'utilisation de 200PUT, DELETE ou de toute autre méthode. Ai-je oublié quelque chose? Tels que Mozilla devenant le patron de W3 et de l'IETF? ;) Ou peut-être qu'ils n'ont tout simplement jamais entendu parler du principe de robustesse de Postel.
système PAUSE du
52
@stian: Cette phrase a été supprimée le 3 février 2013. Probablement parce que quelqu'un l'a lu ici. ;) developer.mozilla.org/en-US/docs/HTTP/…
Christian Strempfer
6
La sémantique de la méthode PUT consiste à ignorer l'état actuel de la ressource, donc retourner un conflit 409 pour un PUT qui échoue en raison d'une modification tierce n'a de sens que si la demande est conditionnelle.
Pedro Werneck
8
@systemPAUSE Belle réponse. Un petit point: si vous n'allez pas retourner un corps de réponse à une opération réussie, je suggère d'utiliser exclusivement un 204. Certains clients (jQuery Ajax, par exemple) s'étoufferont s'ils attendent une réponse de longueur non nulle mais ne l'obtiennent pas. Vous pouvez voir un exemple de cela dans cette question .
nick_w
3
La RFC2616 a peut-être été mise à jour depuis cette réponse. Il n'est mentionné nulle part en 9.6 No response body neededpar rapport à un 200. En fait, le corps de réponse n'est pas du tout mentionné par rapport à un PUT. Il déclare seulementIf an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
James
164

Contrairement à la plupart des réponses ici, je pense en fait que PUT devrait renvoyer la ressource mise à jour (en plus du code HTTP bien sûr).

La raison pour laquelle vous souhaitez renvoyer la ressource en réponse à l'opération PUT est que lorsque vous envoyez une représentation de ressource au serveur, le serveur peut également appliquer un traitement à cette ressource, de sorte que le client souhaite savoir comment fonctionne cette ressource. ressembler à la fin de la demande. (sinon il devra émettre une autre demande GET).

LiorH
la source
3
"le serveur peut également appliquer un traitement à cette ressource": je suis nouveau ceci. Est-ce vraiment reposant?
Raedwald
22
@Raedwald bien sûr. REST n'exige pas que la ressource entière soit mise à jour sur un PUT, bien que cela soit généralement recommandé. Certains champs peuvent ne pas avoir de sens pour la mise à jour - la date de création ou la dernière date de modification, par exemple, ne devrait probablement pas être incluse dans le corps du PUT, mais serait probablement modifiée en raison du PUT. Cela dit, je ne suis pas d'accord avec LiorH pour qu'un PUT se traduise par un retour de la ressource; J'aurais besoin d'un GET après le PUT pour obtenir la ressource mise à jour.
Randolpho
19
@Randolpho REST ne nécessite pas que la ressource entière soit mise à jour sur un PUT , ne devrait-ce pas être le cas d'un PATCH?
Marco Ciambrone
14
@MarcoCiambrone Oui, je suis d'accord et je rétracte mon commentaire précédent. J'ai changé mon air sur REST et PUT - PUT devrait toujours être idempotent et ne devrait jamais être utilisé pour une mise à jour partielle. POST est la seule alternative à moins que PATCH ne soit pris en charge, auquel cas PATCH peut être une bonne alternative. PATCH est un nouveau verbe, cependant, et peut ne pas être pris en charge par certains frameworks côté serveur.
Randolpho
2
La réponse a été écrite bien avant rfc7231, mais la section 4.3.4 indique clairement "La méthode PUT demande que l'état de la ressource cible soit créé ou remplacé par l'état défini par la représentation incluse dans la charge utile du message de demande"
aaaaaa
3

Je pense qu'il est possible que le serveur renvoie du contenu en réponse à un PUT. Si vous utilisez un format d'enveloppe de réponse qui autorise les données latérales (comme le format consommé par ember-data), vous pouvez également inclure d'autres objets qui peuvent avoir été modifiés via des déclencheurs de base de données, etc. (les données latérales sont explicitement réduites # de demandes, et cela semble être un bon endroit pour optimiser.)

Si j'accepte simplement le PUT et que je n'ai rien à signaler, j'utilise le code d'état 204 sans corps. Si j'ai quelque chose à signaler, j'utilise le code de statut 200 et j'inclus un corps.

shaunc
la source
2

La spécification HTTP / 1.1 (section 9.6) décrit les codes de réponse / d'erreur appropriés. Cependant, il ne traite pas du contenu de la réponse.

Qu'attendriez-vous? Un simple code de réponse HTTP (200, etc.) me semble simple et sans ambiguïté.

Brian Agnew
la source
Oui, mais que faire si vous voulez vérifier si les données insérées dans db après un PUT ou un POST représentent vraiment les vraies données que vous souhaitez. Il serait préférable que le HTTP puisse renvoyer le corps de la réponse.
tnkh
1
@tnkh ce que vous proposez est carrément une horrible idée. Effectuez un appel GET distinct après une mise à jour réussie pour obtenir ce que vous voulez. Afin de garantir les performances, introduisez une couche de mise en cache si vous rencontrez des problèmes dans ce département. Nous ne pouvons pas résoudre ces problèmes en jouant avec la logique du «tout va». Ne vous moquez pas des principes de programmation «solides» et de base qui devraient être du bon sens en 2020. C'est une honte!
XDS
@XDS Je reconnais votre première partie du commentaire. Mais je ne peux pas m'arrêter de rouler les yeux après ça. Commentaire hilarant
tnkh
Merci d'avoir expliqué pourquoi vous le trouvez hilarant.
XDS
2

Si le backend de l'API REST est une base de données relationnelle SQL, alors

  1. vous devriez avoir RowVersion dans chaque enregistrement qui peut être mis à jour (pour éviter le problème de mise à jour perdu )
  2. vous devez toujours renvoyer une nouvelle copie de l'enregistrement après PUT (pour obtenir la nouvelle RowVersion ).

Si vous ne vous souciez pas des mises à jour perdues, ou si vous voulez forcer vos clients à faire un GET immédiatement après un PUT, ne retournez rien de PUT.

John Henckel
la source
1

Code de réponse HTTP de 201 pour "Créé" avec un en-tête "Emplacement" pour indiquer où le client peut trouver la ressource nouvellement créée.

dc360
la source
5
Les objets PUT ne sont pas (ou ne devraient pas être) des ressources nouvellement créées
kdazzle
9
@kdazzle PUT peut certainement être une ressource nouvellement créée, et le serait souvent. w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6
Charlie Schliesser
3
Juste pour expliquer un peu mieux mon commentaire. PUT signifie, placez cet article à cet emplacement spécifique, en remplaçant ce qui se trouve actuellement (le cas échéant).
user1751825
3
À droite, "remplacer ce qui existe actuellement" est la phrase clé. Il devrait déjà exister et il est en train d'être remplacé. PUT ne devrait pas être destiné à créer de nouvelles ressources.
Kevin M
3
@KevinM Comme dans le dernier document RFC rfc7231 , il est indiqué que des ressources peuvent être créées: "La méthode PUT demande que l'état de la ressource cible soit créé ou remplacé [...]" et la raison pour laquelle vous pensez que PUT ne peut pas créer nouvelle ressource est parce que vous ne connaissez pas nécessairement l'emplacement de la nouvelle ressource. Mais si vous connaissez son emplacement / identifiant, il peut être créé s'il n'est pas encore là.
Leo Lei
0

J'ai utilisé l'API RESTful dans mes services, et voici mon opinion: D'abord, nous devons arriver à une vue commune: PUTest utilisé pour mettre à jour une ressource pas créer ou obtenir.

J'ai défini des ressources avec: Stateless resourceet Stateful resource:

  • Ressources sans état Pour ces ressources, renvoyez simplement le HttpCode avec un corps vide, c'est suffisant.

  • Ressources avec état Par exemple: la version de la ressource. Pour ce type de ressources, vous devez fournir la version lorsque vous souhaitez la modifier, donc renvoyez la ressource complète ou renvoyez la version au client, afin que le client n'ait pas besoin d'envoyer une demande get après l'action de mise à jour.

Mais , pour un service ou un système, gardezsimple-leclearly,easy to use and maintainc'est la chose la plus importante.

Bruce
la source
6
"PUT est utilisé pour mettre à jour une ressource non créée ou récupérée." - ce n'est ni vrai ni courant. Par spécification, PUT peut créer la ressource. Clair = suivant la spécification communément connue.
Imre Pühvel
-3

Tout comme un corps de demande vide est conforme à l'objectif d'origine d'une demande GET et un corps de réponse vide est conforme à l'objectif d'origine d'une demande PUT.

AnthonyWJones
la source
-3

semble correct ... même si je pense qu'une indication rudimentaire de réussite / échec / temps affiché / # octets reçus / etc. serait préférable.

modifier: je pensais dans le sens de l'intégrité des données et / ou de la tenue des dossiers; des métadonnées telles qu'un hachage MD5 ou un horodatage pour le temps reçu peuvent être utiles pour les fichiers de données volumineux.

Jason S
la source
1
Que diriez-vous de 200 OK dans l'en-tête de réponse d'état? Pensez-vous que c'est suffisant pour dire: "Ça a bien marché, merci?"
AnthonyWJones
l'en-tête de réponse contiendrait le code d'état, et oui, nous parlons de HTTP à ce stade :)
AwkwardCoder
-4

Idéalement, il retournerait une réponse succès / échec.

cgp
la source
13
Pas dans le corps de la réponse, cependant. Le code d'état HTTP est l'endroit pour cela. Peut-être qu'en cas d'erreur, des informations d'erreur étendues pourraient être renvoyées dans la réponse bidy
The Archetypal Paul
-4

Il y a une différence entre l'en-tête et le corps d'une réponse HTTP. PUT ne doit jamais renvoyer de corps, mais doit renvoyer un code de réponse dans l'en-tête. Choisissez simplement 200 s'il a réussi, et 4xx sinon. Il n'y a pas de code retour nul. Pourquoi veux-tu faire cela?

AlexanderJohannesen
la source