http - rest put example




PUT vs. POST in REST (20)

le serveur d'origine peut créer la ressource avec cet URI

Vous utilisez donc POST et probablement, mais pas nécessairement, PUT pour la création de ressources. Vous n'êtes pas obligé de supporter les deux. Pour moi, POST suffit parfaitement. C'est donc une décision de conception.

Comme votre citation l'a mentionné, vous utilisez PUT pour créer aucune ressource affectée à un IRI et vous souhaitez néanmoins créer une ressource. Par exemple, PUT /users/123/passwordremplace généralement l'ancien mot de passe par un nouveau, mais vous pouvez l'utiliser pour créer un mot de passe s'il n'existe pas déjà (par exemple, par des utilisateurs récemment enregistrés ou par la restauration d'utilisateurs interdits).

Selon la spécification HTTP / 1.1:

La méthode POST est utilisée pour demander au serveur d'origine d'accepter l'entité incluse dans la demande en tant que nouveau subordonné de la ressource identifiée par l' Request-URI de Request-Line dans la ligne de Request-Line

En d'autres termes, POST est utilisé pour créer .

La méthode PUT demande à ce que l'entité incluse soit stockée sous l' Request-URI fourni. Si l' Request-URI fait référence à une ressource déjà existante, l'entité incluse DEVRAIT être considérée comme une version modifiée de celle résidant sur le serveur d'origine. Si Request-URI ne pointe pas vers une ressource existante et que cet URI peut être défini en tant que nouvelle ressource par l'agent utilisateur demandeur, le serveur d'origine peut créer la ressource avec cet URI. "

C'est-à-dire que PUT est utilisé pour créer ou mettre à jour .

Alors, lequel devrait être utilisé pour créer une ressource? Ou faut-il supporter les deux?


Résumé:

Créer:

Peut être effectué à la fois avec PUT ou POST de la manière suivante:

METTRE

Crée LA nouvelle ressource avec newResourceId comme identifiant, sous l'URI / resources ou collection .

PUT /resources/<newResourceId> HTTP/1.1 

POSTER

Crée une nouvelle ressource sous l'URI / resources de / resources. Généralement, l'identifiant est renvoyé par le serveur.

POST /resources HTTP/1.1

Mettre à jour:

Ne peut être exécuté avec PUT de la manière suivante:

METTRE

Met à jour la ressource avec existingResourceId en tant qu'identificateur, sous l'URI / resources ou collection .

PUT /resources/<existingResourceId> HTTP/1.1

Explication:

Lorsque vous traitez avec REST et URI en général, vous avez générique à gauche et spécifique à droite . Les génériques sont généralement appelés des collections et les éléments plus spécifiques peuvent être appelés des ressources . Notez qu'une ressource peut contenir une collection .

Exemples:

<- générique - spécifique ->

URI: website.com/users/john
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource

URI:website.com/users/john/posts/23
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource
posts        - collection of posts from john
23           - post from john with identifier 23, also a resource

Lorsque vous utilisez POST, vous faites toujours référence à une collection . Ainsi, chaque fois que vous dites:

POST /users HTTP/1.1

vous publiez un nouvel utilisateur dans la collection d' utilisateurs .

Si vous continuez et essayez quelque chose comme ça:

POST /users/john HTTP/1.1

cela fonctionnera, mais vous dites sémantiquement que vous voulez ajouter une ressource à la collection john sous la collection users .

Une fois que vous utilisez PUT, vous vous référez à une ressource ou à un seul élément, éventuellement dans une collection . Alors quand tu dis:

PUT /users/john HTTP/1.1

vous indiquez à la mise à jour du serveur ou créez, si elle n’existe pas, la ressource john dans la collection users .

Spec:

Permettez-moi de souligner certaines parties importantes de la spécification:

POSTER

La méthode POST est utilisée pour demander au serveur d'origine d' accepter l'entité incluse dans la demande en tant que nouveau subordonné de la ressource identifiée par l'URI de demande dans la ligne de demande.

Par conséquent, crée une nouvelle ressource sur une collection .

METTRE

La méthode PUT demande à ce que l'entité incluse soit stockée sous l'URI de demande fourni. Si l'URI de demande fait référence à une ressource déjà existante , l'entité incluse DEVRAIT être considérée comme une version modifiée de celle résidant sur le serveur d'origine. Si Request-URI ne pointe pas vers une ressource existante et que cet URI peut être défini en tant que nouvelle ressource par l'agent utilisateur demandeur, le serveur d'origine peut créer la ressource avec cet URI. "

Par conséquent, créez ou mettez à jour en fonction de l'existence de la ressource .

Référence:


J'aimerais ajouter mon conseil "pragmatique". Utilisez PUT lorsque vous connaissez "l'identifiant" permettant d'extraire l'objet que vous enregistrez. L'utilisation de PUT ne fonctionnera pas très bien si vous avez besoin, par exemple, d'un identifiant généré par une base de données à renvoyer pour que vous puissiez effectuer des recherches ou des mises à jour futures.

Donc: pour sauvegarder un utilisateur existant, ou un utilisateur dont le client génère l'identifiant et vérifie que l'identifiant est unique:

PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
Host: mydomain.com

GET /user/12345 HTTP/1.1  <-- return that user
Host: mydomain.com

Sinon, utilisez POST pour créer initialement l'objet et PUT pour le mettre à jour:

POST /user HTTP/1.1   <--- create the user, server returns 12345
Host: mydomain.com

PUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com

POST signifie "créer un nouveau" comme dans "Voici l'entrée pour créer un utilisateur, créez-le pour moi".

PUT signifie "insérer, remplacer s'il existe déjà" comme dans "Voici les données pour l'utilisateur 5".

Vous POST sur example.com/users puisque vous ne connaissez pas encore l'URL de l'utilisateur, vous souhaitez que le serveur le crée.

Vous POUVEZ sur example.com/users/id puisque vous voulez remplacer / créer un utilisateur spécifique .

Poster deux fois avec les mêmes données signifie créer deux utilisateurs identiques avec des identifiants différents. PUTing deux fois avec les mêmes données crée le premier utilisateur et le remet au même état la deuxième fois (sans modification). Puisque vous vous retrouvez dans le même état après une opération PUT, peu importe le nombre de fois que vous l’effectuez, on dit qu’il est "tout aussi puissant" à chaque fois - idempotent. Ceci est utile pour réessayer automatiquement les demandes. Pas plus "êtes-vous sûr de vouloir renvoyer" lorsque vous appuyez sur le bouton retour du navigateur.

Un conseil général est d'utiliser POST lorsque vous avez besoin que le serveur contrôle la génération d'URL de vos ressources. Utilisez PUT autrement. Préfère PUT au POST.


Utilisez POST pour créer et PUT pour mettre à jour. C'est comme ça que Ruby on Rails le fait.

PUT    /items/1      #=> update
POST   /items        #=> create

Vous pouvez trouver des affirmations sur le Web qui disent

Ni est tout à fait raison.

Mieux vaut choisir entre PUT et POST en fonction de l' idempotence de l'action.

PUT implique de mettre une ressource - en remplaçant complètement tout ce qui est disponible à l'URL donnée par un élément différent. Par définition, un PUT est idempotent. Faites-le autant de fois que vous le souhaitez et le résultat est identique. x=5 est idempotent. Vous pouvez PUT une ressource si elle existait auparavant ou non (par exemple, pour créer, ou pour mettre à jour)!

Le POST met à jour une ressource, ajoute une ressource subsidiaire ou provoque une modification. Un POST n’est pas idempotent, au même titre que x++ n’est pas idempotent.

Par cet argument, PUT sert à créer lorsque vous connaissez l'URL de la chose que vous allez créer. POST peut être utilisé pour créer lorsque vous connaissez l'URL de la "fabrique" ou du gestionnaire de la catégorie de choses que vous souhaitez créer.

alors:

POST /expense-report

ou:

PUT  /expense-report/10929

La décision d'utiliser PUT ou POST pour créer une ressource sur un serveur avec une API HTTP + REST est basée sur le propriétaire de la structure d'URL. Le fait que le client connaisse ou participe à la définition de la structure d'URL est un couplage inutile, qui s'apparente aux couplages indésirables résultant de la SOA. La raison pour laquelle REST est si populaire est le type de couplage qui s’échappe. Par conséquent, la méthode appropriée à utiliser est POST. Il existe des exceptions à cette règle et elles se produisent lorsque le client souhaite conserver le contrôle de la structure d'emplacement des ressources qu'il déploie. Ceci est rare et signifie probablement que quelque chose ne va pas.

À ce stade, certaines personnes diront que si des URL RESTful sont utilisées, le client connaît l'URL de la ressource et, par conséquent, un PUT est acceptable. Après tout, c’est la raison pour laquelle les URL canoniques, normalisées, Ruby on Rails, Django sont importantes. Regardez l’API de Twitter… bla bla bla. Ces personnes doivent comprendre qu'il n'existe pas d'URL reposante et que Roy Fielding lui-même déclare que :

Une API REST ne doit pas définir de noms de ressources fixes ni de hiérarchies (un couplage évident entre client et serveur). Les serveurs doivent avoir la liberté de contrôler leur propre espace de noms. Au lieu de cela, autorisez les serveurs à expliquer aux clients comment construire les URI appropriés, comme cela est fait dans les formulaires HTML et les modèles d'URI, en définissant ces instructions dans les types de média et les relations de liaison. [Une défaillance ici implique que les clients assument une structure de ressources en raison d'informations hors bande, telles qu'une norme spécifique à un domaine, qui est l'équivalent orienté données du couplage fonctionnel du protocole RPC].

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

L'idée d'une URL RESTful est en réalité une violation de REST car le serveur est responsable de la structure de l'URL et devrait être libre de décider de son utilisation pour éviter le couplage. Si cela vous trouble, vous en apprendrez plus sur l’importance de la découverte de soi dans la conception des API.

L'utilisation de POST pour créer des ressources est un facteur de conception, car POST n'est pas idempotent. Cela signifie que répéter un POST plusieurs fois ne garantit pas le même comportement à chaque fois. Cela effraie les gens d'utiliser PUT pour créer des ressources alors qu'ils ne le devraient pas. Ils savent que c'est faux (POST est pour CREATE) mais ils le font quand même parce qu'ils ne savent pas comment résoudre ce problème. Cette préoccupation est démontrée dans la situation suivante:

  1. Le client envoie une nouvelle ressource au serveur.
  2. Le serveur traite la demande et envoie une réponse.
  3. Le client ne reçoit jamais la réponse.
  4. Le serveur ignore que le client n'a pas reçu la réponse.
  5. Le client n'a pas d'URL pour la ressource (par conséquent, PUT n'est pas une option) et répète le POST.
  6. Le POST n’est pas idempotent et le serveur…

L'étape 6 est l'endroit où les gens se demandent souvent quoi faire. Cependant, il n'y a aucune raison de créer un kludge pour résoudre ce problème. Au lieu de cela, HTTP peut être utilisé comme spécifié dans RFC 2616 et le serveur répond:

10.4.10 409 Conflit

La demande n'a pas pu être complétée en raison d'un conflit avec l'état actuel de la ressource. Ce code n'est autorisé que dans les cas où l'utilisateur devrait pouvoir résoudre le conflit et resoumettre la demande. Le corps de réponse DEVRAIT inclure suffisamment

informations permettant à l’utilisateur de reconnaître la source du conflit. Idéalement, l'entité de réponse inclurait suffisamment d'informations pour permettre à l'utilisateur ou à l'agent d'utilisateur de résoudre le problème. cependant, cela pourrait ne pas être possible et n'est pas requis.

Les conflits sont plus susceptibles de se produire en réponse à une demande PUT. Par exemple, si le contrôle de version était utilisé et que l'entité en cours PUT incluait des modifications d'une ressource incompatibles avec celles effectuées par une requête précédente (tierce partie), le serveur pourrait utiliser la réponse 409 pour indiquer qu'il ne pouvait pas terminer la demande. . Dans ce cas, l'entité de réponse contiendra probablement une liste des différences entre les deux versions dans un format défini par la réponse Content-Type.

Répondre avec un code d'état de 409 Le conflit est le recours correct pour les raisons suivantes :

  • L'exécution d'un POST de données dont l'ID correspond à une ressource déjà présente dans le système constitue «un conflit avec l'état actuel de la ressource».
  • Puisque l’important est que le client comprenne que le serveur dispose de la ressource et prend les mesures appropriées. Il s'agit d'une «situation (s) dans laquelle l'utilisateur devrait pouvoir résoudre le conflit et soumettre à nouveau la demande».
  • Une réponse contenant l'URL de la ressource avec l'ID en conflit et les conditions préalables appropriées pour la ressource fournirait «suffisamment d'informations à l'utilisateur ou à l'agent d'utilisateur pour résoudre le problème», ce qui est le cas idéal selon la RFC 2616.

Mise à jour basée sur la publication de la RFC 7231 pour remplacer 2616

La RFC 7231 est conçue pour remplacer 2616 et, dans la section 4.3.3, décrit la réponse possible suivante pour un POST

Si le résultat du traitement d'un POST équivaut à la représentation d'une ressource existante, un serveur d'origine PEUT rediriger l'agent utilisateur vers cette ressource en envoyant une réponse 303 (voir autre) avec l'identificateur de la ressource existante dans le champ Emplacement. Cela présente l'avantage de fournir à l'agent d'utilisateur un identifiant de ressource et de transférer la représentation via un procédé plus propice à la mise en cache partagée, mais au prix d'une requête supplémentaire si l'agent d'utilisateur ne dispose pas déjà de la représentation en cache.

Il peut maintenant être tentant de simplement renvoyer un 303 dans le cas où un POST est répété. Cependant, le contraire est vrai. Le renvoi d'un 303 n'a de sens que si plusieurs demandes de création (créant des ressources différentes) renvoient le même contenu.Un exemple serait un "merci d'avoir envoyé votre message de demande" que le client n'a pas besoin de télécharger à nouveau à chaque fois. La RFC 7231 maintient toujours dans la section 4.2.2 que le POST ne doit pas être idempotent et continue à soutenir que le POST doit être utilisé pour créer.

Pour plus d'informations à ce sujet, lisez cet article .


Nouvelle réponse (maintenant que je comprends mieux le reste):

PUT est simplement une déclaration du contenu que le service devrait désormais utiliser pour restituer des représentations de la ressource identifiée par le client; POST est une déclaration du contenu que le service devrait désormais contenir (éventuellement dupliqué), mais il appartient au serveur de déterminer ce contenu.

PUT x(si xidentifie une resource ): "Remplace le contenu de la ressource identifiée par xpar mon contenu."

PUT x(si xn'identifie pas une ressource): "Créez une nouvelle ressource contenant mon contenu et utilisez-le xpour l'identifier."

POST x: "Stocker mon contenu et me donner un identifiant que je peux utiliser pour identifier une ressource (ancienne ou nouvelle) contenant ledit contenu (éventuellement mélangé avec un autre contenu). Cette ressource doit être identique ou subordonnée à celle qui xidentifie." « Y « ressource s est subordonnée à x » ressource s » est généralement , mais pas nécessairement mis en œuvre en faisant y un sous - chemin de x (par exemple x = /fooet y = /foo/bar) et modifier la représentation (s) de x ressources de l » afin de refléter l'existence d'une nouvelle ressource, par exemple avec un hyperlien vers yde la ressource et des métadonnées. Seule cette dernière solution est essentielle à une bonne conception, car les URL sont opaques dans REST. Vous êtes censé utiliser hypermédia au lieu de la construction d’URL côté client pour traverser le service de toute façon.

Dans REST, une ressource contenant du "contenu" n'existe pas. Je fais référence à "contenu" aux données que le service utilise pour restituer des représentations de manière cohérente. Il se compose généralement de lignes liées dans une base de données ou un fichier (par exemple, un fichier image). Il appartient au service de convertir le contenu de l'utilisateur en quelque chose que le service peut utiliser, par exemple, la conversion d'une charge JSON en instructions SQL.

Réponse originale (peut-être plus facile à lire) :

PUT /something(s'il /somethingexiste déjà): "Prends ce que tu as /somethinget remplace-le par ce que je te donne."

PUT /something(si /somethingn'existe pas déjà): "Prends ce que je te donne et mets-le à /something."

POST /something: "Prends ce que je te donne et mets-le où tu veux /something, pourvu que tu me donnes son URL quand tu auras fini."


Bien qu’il existe probablement une manière agnostique de les décrire, cela semble en contradiction avec diverses déclarations issues de réponses à des sites Web.

Soyons très clairs et directs ici. Si vous êtes un développeur .NET utilisant l'API Web, voici les faits (extraits de la documentation de l'API Microsoft): http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations :

1. PUT = UPDATE (/api/products/id)
2. MCSD Exams 2014 -  UPDATE = PUT, there are **NO** multiple answers for that question period.

Bien sûr, vous "pouvez" utiliser "POST" pour mettre à jour, mais il suffit de suivre les conventions établies pour vous avec votre cadre donné. Dans mon cas, il s’agit de .NET / Web API, donc PUT est pour UPDATE, il n’ya pas de débat.

J'espère que cela aidera tous les développeurs Microsoft qui liront tous les commentaires avec les liens de sites Web Amazon et Sun / Java.


De manière très simple, je prends l'exemple de la chronologie de Facebook.

Cas 1: Lorsque vous publiez quelque chose sur votre timeline, il s'agit d'une nouvelle entrée. Donc, dans ce cas, ils utilisent la méthode POST car celle-ci n'est pas idempotente.

Cas 2: Si votre ami commente la publication pour la première fois, cela créera également une nouvelle entrée dans la base de données afin que la méthode POST soit utilisée.

Cas 3: Si votre ami modifie son commentaire, dans ce cas, il possède un identifiant de commentaire. Il met donc à jour un commentaire existant au lieu de créer une nouvelle entrée dans la base de données. Par conséquent, pour ce type d'opération, utilisez la méthode PUT car elle est idempotente. *

Sur une seule ligne, utilisez POST pour ajouter une nouvelle entrée à la base de données et PUT pour mettre à jour un élément de la base de données.


La plupart du temps, vous les utiliserez comme ceci:

  • POSTER une ressource dans une collection
  • PUT une ressource identifiée par collection /: id

Par exemple:

  • POST / articles
  • PUT / articles / 1234

Dans les deux cas, le corps de la demande contient les données de la ressource à créer ou à mettre à jour. D'après les noms de route, il devrait être évident que POST n'est pas idempotent (si vous l'appelez 3 fois, 3 objets seront créés), mais PUT est idempotent (si vous l'appelez 3 fois, le résultat est identique). PUT est souvent utilisé pour l'opération "upsert" (création ou mise à jour), mais vous pouvez toujours renvoyer une erreur 404 si vous souhaitez uniquement l'utiliser pour modifier.

Notez que POST "crée" un nouvel élément dans la collection et que PUT "remplace" un élément à une URL donnée, mais il est très courant d’utiliser PUT pour les modifications partielles, c’est-à-dire de ne l’utiliser que pour mettre à jour les ressources existantes. modifiez uniquement les champs inclus dans le corps (en ignorant les autres champs). Ceci est techniquement incorrect, si vous voulez être puriste REST, PUT doit remplacer la totalité de la ressource et vous devez utiliser PATCH pour la mise à jour partielle. Personnellement, cela m'est égal car le comportement est clair et cohérent sur tous vos points de terminaison d'API.

N'oubliez pas que REST est un ensemble de conventions et de consignes permettant de garder votre API simple. Si vous vous retrouvez avec une solution de contournement compliquée juste pour cocher la case "RESTfull", vous échouez alors;)


La sémantique est supposée être différente, en ce sens que "PUT", comme "GET" est supposé être idempotent, ce qui signifie que vous pouvez faire la même requête PUT exactement plusieurs fois et le résultat sera comme si vous ne l'aviez exécutée qu'une fois.

Je décrirai les conventions qui, à mon avis, sont les plus largement utilisées et les plus utiles:

Lorsque vous mettez une ressource sur une URL particulière, elle doit être enregistrée sur cette URL ou quelque chose du même genre.

Lorsque vous publiez une ressource sur une URL donnée, vous publiez souvent une information connexe sur cette URL. Cela implique que la ressource à l'URL existe déjà.

Par exemple, lorsque vous souhaitez créer un nouveau flux, vous pouvez le PUT sur une URL. Mais lorsque vous souhaitez poster un message dans un flux existant, vous en envoyez à son URL.

En ce qui concerne la modification des propriétés du flux, vous pouvez le faire avec PUT ou POST. Fondamentalement, utilisez seulement "PUT" lorsque l'opération est idempotente - sinon utilisez POST.

Notez cependant que tous les navigateurs modernes ne prennent pas en charge les verbes HTTP autres que GET ou POST.


Outre les différences suggérées par d'autres, je souhaite en ajouter une de plus.

Dans la méthode POST , vous pouvez envoyer des paramètres de corps dansform-data

Dans la méthode PUT , vous devez envoyer des paramètres de corps dansx-www-form-urlencoded

Entête Content-Type:application/x-www-form-urlencoded

Selon cela, vous ne pouvez pas envoyer de fichiers ou de données en plusieurs parties avec la méthode PUT.

MODIFIER

Le type de contenu "application / x-www-form-urlencoded" ne permet pas d'envoyer de grandes quantités de données binaires ou de texte contenant des caractères non-ASCII. Le type de contenu "multipart / form-data" doit être utilisé pour soumettre des formulaires contenant des fichiers, des données non-ASCII et des données binaires.

Ce qui signifie que si vous devez soumettre

fichiers, données non-ASCII et données binaires

vous devriez utiliser la méthode POST


Ruby on Rails 4.0 utilisera la méthode 'PATCH' au lieu de PUT pour effectuer des mises à jour partielles.

RFC 5789 dit à propos de PATCH (depuis 1995):

Une nouvelle méthode est nécessaire pour améliorer l'interopérabilité et éviter les erreurs. La méthode PUT est déjà définie pour remplacer une ressource par un nouveau corps complet et ne peut pas être réutilisée pour effectuer des modifications partielles. Sinon, les mandataires et les caches, et même les clients et les serveurs, risquent d'être confus quant au résultat de l'opération. Le POST est déjà utilisé, mais sans interopérabilité étendue (pour l’un, il n’existe aucun moyen standard de découvrir le support du format de patch). PATCH a été mentionné dans les spécifications HTTP précédentes, mais pas complètement défini.

" Edge Rails: PATCH est la nouvelle méthode HTTP principale pour les mises à jour ", explique-t-il.


Voici une règle simple:

PUT vers une URL doit être utilisé pour mettre à jour ou créer la ressource pouvant se trouver sur cette URL.

Le POST sur une URL doit être utilisé pour mettre à jour ou créer une ressource située dans une autre URL ("subordonnée") ou non localisable via HTTP.


Au risque de reformuler ce qui a déjà été dit, il semble important de rappeler que PUT implique que le client contrôle ce que l' URL va devenir lors de la création d'une ressource. Une partie du choix entre PUT et POST va donc dépendre du degré de confiance que le client peut avoir pour fournir une URL correcte, normalisée et cohérente avec le schéma de votre URL.

Lorsque vous ne pouvez pas entièrement faire confiance au client pour qu'il agisse correctement, il est préférable d'utiliser POST pour créer un nouvel élément, puis de renvoyer l'URL au client dans la réponse.


Il semble toujours y avoir une certaine confusion quant au moment d'utiliser HTTP POST par rapport à la méthode HTTP PUT pour les services REST. La plupart des développeurs essaieront d'associer directement les opérations CRUD aux méthodes HTTP. Je dirai que ce n'est pas correct et que l'on ne peut pas simplement associer les concepts CRUD aux méthodes HTTP. C'est:

Create => HTTP PUT
Retrieve => HTTP GET
Update => HTTP POST
Delete => HTTP DELETE

Il est vrai que les opérations R (etrieve) et D (elete) des opérations CRUD peuvent être mappées directement aux méthodes HTTP GET et DELETE, respectivement. Cependant, la confusion réside dans les opérations C (créer) et U (mettre à jour). Dans certains cas, on peut utiliser le PUT pour une création alors que dans d'autres cas, un POST sera requis. L'ambiguïté réside dans la définition d'une méthode HTTP PUT par rapport à une méthode HTTP POST.

Selon les spécifications HTTP 1.1, les méthodes GET, HEAD, DELETE et PUT doivent être idempotentes et la méthode POST n'est pas idempotente. C'est-à-dire qu'une opération est idempotente si elle peut être effectuée sur une ressource une ou plusieurs fois et renvoyer toujours le même état de cette ressource. Alors qu'une opération non idempotente peut renvoyer un état modifié de la ressource d'une requête à une autre. Par conséquent, dans une opération non idempotente, rien ne garantit que l’on obtiendra le même état d’une ressource.

Sur la base de la définition idempotente ci-dessus, mon approche de la méthode HTTP PUT et de la méthode HTTP POST pour les services REST est la suivante: Utilisez la méthode HTTP PUT lorsque:

The client includes all aspect of the resource including the unique identifier to uniquely identify the resource. Example: creating a new employee.
The client provides all the information for a resource to be able to modify that resource.This implies that the server side does not update any aspect of the resource (such as an update date).

Dans les deux cas, ces opérations peuvent être effectuées plusieurs fois avec les mêmes résultats. C'est-à-dire que la ressource ne sera pas modifiée en demandant l'opération plus d'une fois. Par conséquent, une véritable opération idempotente. Utilisez la méthode HTTP POST lorsque:

The server will provide some information concerning the newly created resource. For example, take a logging system. A new entry in the log will most likely have a numbering scheme which is determined on the server side. Upon creating a new log entry, the new sequence number will be determined by the server and not by the client.
On a modification of a resource, the server will provide such information as a resource state or an update date. Again in this case not all information was provided by the client and the resource will be changing from one modification request to the next. Hence a non idempotent operation.

Conclusion

Ne pas directement corréler et mapper les opérations CRUD aux méthodes HTTP pour les services REST. L'utilisation d'une méthode HTTP PUT par rapport à une méthode HTTP POST doit être basée sur l'aspect idempotent de cette opération. Autrement dit, si l'opération est idempotente, utilisez la méthode HTTP PUT. Si l'opération n'est pas idempotente, utilisez la méthode HTTP POST.


J'aime ce conseil, tiré de la définition de PUT de la RFC 2616 :

La différence fondamentale entre les requêtes POST et PUT est reflétée dans la signification différente de l'URI de demande. L'URI dans une demande POST identifie la ressource qui gérera l'entité incluse. Cette ressource peut être un processus acceptant les données, une passerelle vers un autre protocole ou une entité distincte acceptant les annotations. En revanche, l'URI dans une demande PUT identifie l'entité jointe à la demande - l'agent d'utilisateur sait ce que l'URI est destiné et le serveur NE DOIT PAS tenter d'appliquer la demande à une autre ressource.

Ceci concorde avec les autres conseils donnés ici, à savoir que PUT s’applique mieux aux ressources qui ont déjà un nom et que POST convient bien pour créer un nouvel objet sous une ressource existante (et laisser le nom du serveur le nommer).

J'interprète cela, ainsi que les exigences d'idempotency sur PUT, comme signifiant que:

  • POST est utile pour créer de nouveaux objets dans une collection (et créer n'a pas besoin d'être idempotent)
  • PUT est utile pour mettre à jour des objets existants (et update doit être idempotent)
  • POST peut également être utilisé pour des mises à jour non idempotentes d'objets existants (en particulier, modifier une partie d'un objet sans spécifier le tout. Si vous y réfléchissez, la création d'un nouveau membre d'une collection est en fait un cas particulier de ce type de processus. mise à jour, du point de vue de la collection)
  • PUT peut également être utilisé pour créer si et seulement si vous autorisez le client à nommer la ressource. Mais comme les clients REST ne sont pas supposés faire des hypothèses sur la structure des URL, cela est moins conforme à l’esprit des choses.

Le POST, c'est comme envoyer une lettre dans une boîte aux lettres ou un courrier électronique dans une file d'attente. PUT est comme quand vous mettez un objet dans un trou ou un emplacement sur une étagère (il a une adresse connue).

Avec POST, vous publiez à l'adresse de la file d'attente ou de la collection. Avec PUT, vous mettez à l'adresse de l'ARTICLE.

PUT est idempotent. Vous pouvez envoyer la demande 100 fois et ce ne sera pas grave. Le POST n’est pas idempotent. Si vous envoyez la demande 100 fois, vous recevrez 100 courriels ou 100 lettres dans votre boîte aux lettres.

Une règle générale: si vous connaissez l'identifiant ou le nom de l'élément, utilisez PUT. Si vous souhaitez que l'identifiant ou le nom de l'élément soit attribué par la partie destinataire, utilisez POST.


Les nouveaux lecteurs de ce sujet seront frappés par la discussion sans fin sur ce que vous devriez faire et par l’absence relative de leçons tirées de l’expérience. Le fait que REST soit "préféré" par rapport à SOAP est, je suppose, un apprentissage de haut niveau de l’expérience, mais bonté avons-nous progressé à partir de là? Nous sommes en 2016. La thèse de Roy date de 2000. Qu'est-ce que nous avons développé? Était-ce amusant?Était-ce facile à intégrer? Soutenir? Acceptera-t-il la montée des smartphones et des connexions mobiles instables?

Selon moi, les réseaux de la vie réelle ne sont pas fiables. Délai d'expiration des demandes. Les connexions sont réinitialisées. Les réseaux sont en panne pendant des heures ou des jours à la fois. Les trains entrent dans des tunnels avec des utilisateurs mobiles à bord. Pour toute demande donnée (comme cela est parfois reconnu dans toutes les discussions), la demande peut tomber dans l'eau pendant son trajet ou la réponse peut tomber dans l'eau lors de son retour. Dans ces conditions, émettre des demandes PUT, POST et DELETE directement contre des ressources substantielles m'a toujours semblé un peu brutal et naïf.

HTTP ne fait rien pour assurer un achèvement fiable de la demande-réponse, et c'est très bien parce que c'est le travail des applications sensibles au réseau. En développant une telle application, vous pouvez parcourir les étapes pour utiliser PUT au lieu de POST, puis plusieurs étapes pour donner un certain type d'erreur sur le serveur si vous détectez des demandes en double. De retour chez le client, vous devez ensuite parcourir des étapes pour interpréter ces erreurs, récupérer, revalider et rediffuser.

Ou vous pouvez le faire : considérez vos demandes non sécurisées comme des ressources éphémères à utilisateur unique (appelons-les des actions). Les clients demandent une nouvelle "action" sur une ressource substantive avec un POST vide pour la ressource. Le POST ne sera utilisé que pour cela. Lorsqu'il est en toute sécurité en possession de l'URI de l'action fraîchement imprimée, le client PUT la demande non sécurisée à l'URI de l'action, pas à la ressource cible . La résolution de l'action et la mise à jour de la "vraie" ressource constituent le travail de votre API et sont ici découplées du réseau non fiable.

Le serveur gère l'entreprise, renvoie la réponse et la stocke contre l'URI d'action convenu . Si quelque chose ne va pas, le client répète la demande (comportement naturel!), Et si le serveur l'a déjà vue, il répète la réponse stockée et ne fait rien d'autre .

Vous remarquerez rapidement la similitude avec les promesses: nous créons et retournons l’espace réservé pour le résultat avant de faire quoi que ce soit. Également comme une promesse, une action peut réussir ou échouer une fois, mais son résultat peut être extrait à plusieurs reprises.

Mieux encore, nous donnons aux applications d'envoi et de réception une occasion de lier l'action identifiée de manière unique à l'unicité dans leurs environnements respectifs. Et nous pouvons commencer à exiger et à appliquer !, un comportement responsable de la part des clients: répétez vos demandes autant de fois que vous le souhaitez, mais ne créez pas de nouvelle action tant que vous ne disposez pas du résultat définitif de l'existant.

En tant que tel, de nombreux problèmes épineux disparaissent. Les demandes d'insertion répétées ne créent pas de doublons et nous ne créons pas la ressource réelle tant que nous ne sommes pas en possession des données. (les colonnes de la base de données peuvent rester non nullables). Les demandes de mise à jour répétées n'atteignent pas les états incompatibles et n'écrasent pas les modifications ultérieures. Les clients peuvent (ré) extraire et traiter de manière transparente la confirmation d'origine pour quelque raison que ce soit (client bloqué, réponse manquante, etc.).

Les demandes de suppression successives peuvent voir et traiter la confirmation d'origine, sans générer d'erreur 404. Si les choses prennent plus de temps que prévu, nous pouvons répondre provisoirement et le client peut consulter le résultat final. La plus belle partie de ce modèle est sa propriété Kung-Fu (Panda). Nous prenons une faiblesse, la propension des clients à répéter une demande chaque fois qu'ils ne comprennent pas la réponse, et la transformons en une force :-)

Avant de me dire que ce n’est pas RESTful, veuillez considérer les nombreuses manières dont les principes REST sont respectés. Les clients ne construisent pas d'URL. L'API reste découvrable, avec toutefois un léger changement de sémantique. Les verbes HTTP sont utilisés de manière appropriée. Si vous pensez que c'est un énorme changement à mettre en œuvre, je peux vous dire d'expérience que ce n'est pas le cas.

Si vous pensez que vous avez des quantités énormes de données à stocker, parlons-en des volumes: une confirmation de mise à jour typique représente une fraction de kilo-octet. HTTP vous donne actuellement une minute ou deux pour répondre définitivement. Même si vous ne stockez que des actions pendant une semaine, les clients ont de grandes chances de les rattraper. Si vous avez des volumes très élevés, vous souhaiterez peut-être un magasin de valeurs de clé dédié compatible avec l'acide, ou une solution en mémoire.





put