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 le _Request-URI
_ dans le _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 le _Request-URI
_ fourni. Si le _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 le _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?
Globalement:
PUT et POST peuvent être utilisés pour créer.
Vous devez demander "à quoi effectuez-vous l'action?" pour distinguer ce que vous devriez utiliser. Supposons que vous concevez une API pour poser des questions. Si vous voulez utiliser POST, vous pouvez le faire pour une liste de questions. Si vous souhaitez utiliser PUT, vous pouvez le faire pour une question donnée.
Les deux peuvent être utilisés, donc lequel dois-je utiliser dans ma conception RESTful:
Vous n'avez pas besoin de supporter à la fois PUT et POST.
Ce qui est utilisé est laissé à vous. Mais n'oubliez pas d'utiliser le bon en fonction de l'objet que vous référencez dans la requête.
Quelques considérations:
Un exemple:
J'ai écrit ce qui suit dans le cadre d'une autre réponse sur SO à ce sujet :
POST:
Utilisé pour modifier et mettre à jour une ressource
POST /questions/<existing_question> HTTP/1.1 Host: www.example.com/
Notez que ce qui suit est une erreur:
POST /questions/<new_question> HTTP/1.1 Host: www.example.com/
Si l'URL n'est pas encore créée, vous ne devez pas utiliser POST pour le créer tout en spécifiant le nom. Cela devrait entraîner une erreur "ressource introuvable" car
<new_question>
n'existe pas encore. Vous devriez d'abord placer la ressource<new_question>
sur le serveur.Vous pouvez cependant faire quelque chose comme ceci pour créer des ressources en utilisant POST:
POST /questions HTTP/1.1 Host: www.example.com/
Notez que dans ce cas, le nom de la ressource n’est pas spécifié, le nouveau chemin d’URL des objets vous sera renvoyé.
PUT:
Utilisé pour créer une ressource ou l'écraser. Pendant que vous spécifiez la nouvelle URL des ressources.
Pour une nouvelle ressource:
PUT /questions/<new_question> HTTP/1.1 Host: www.example.com/
Pour écraser une ressource existante:
PUT /questions/<existing_question> HTTP/1.1 Host: www.example.com/
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 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 le même. x=5
est idempotent. Vous pouvez PUT une ressource si elle existait auparavant ou non (par exemple, pour créer, ou pour mettre à jour)!
POST met à jour une ressource, ajoute une ressource subsidiaire ou provoque une modification. Un POST n'est pas idempotent, de la même manière 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 spécification pertinente pour PUT et POST est RFC 2616 §9.5ff.
POST crée une ressource enfant, donc POST to /items
crée une ressource située sous la ressource /items
. Par exemple. /items/1
. Envoyer le même paquet de messages deux fois créera deux ressources.
PUT permet de créer ou de remplacer une ressource sur un RL connue du client.
Par conséquent: PUT est uniquement un candidat pour CREATE où le client connaît déjà l'URL avant la création de la ressource. Par exemple. /blogs/nigel/entry/when_to_use_post_vs_put
car le titre est utilisé comme clé de ressource
PUT remplace la ressource à l'URL connue, si elle existe déjà, envoyer deux fois la même demande n'a aucun effet. En d'autres termes, les appels à PUT sont idempotents.
La RFC se lit comme ceci:
La différence fondamentale entre les demandes 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. Si le serveur souhaite que la demande soit appliquée à un autre URI,
Note: PUT a été principalement utilisé pour mettre à jour des ressources (en les remplaçant dans leur intégralité), mais récemment, l'utilisation de PATCH pour mettre à jour des ressources existantes s'est accélérée, car PUT spécifie qu'il remplace l'intégralité de la ressource. RFC 5789.
Mise à jour 2018: Il est possible d'éviter le PUT. Voir "REPOS SANS PUT"
Avec la technique "REST without PUT", l’idée est que les consommateurs sont obligés de publier de nouvelles ressources de requête "nominatives". Comme indiqué précédemment, le changement d’adresse postale d’un client est un POST en une nouvelle ressource "ChangeOfAddress", et non un PUT d’une ressource "Client" avec une valeur de champ d’adresse postale différente.
tiré de Conception d'API REST - Modélisation de ressources par Prakash Subramaniam de Thoughtworks
Cela oblige l'API à éviter les problèmes de transition d'état lorsque plusieurs clients mettent à jour une seule ressource et à mieux correspondre à la génération d'événements et à CQRS. Lorsque le travail est effectué de manière asynchrone, le postage de la transformation et l'attente de son application semble approprié.
Peut être exécuté à la fois avec PUT ou POST de la manière suivante:
METTRE
CréeLEnouvelle ressource avecnewResourceIden tant qu'identificateur, sous l'URI/resources/oucollection.
PUT /resources/<newResourceId> HTTP/1.1
POST
CréeAnouvelle ressource sous l'URI/resources, oucollection. Généralement, l'identifiant est renvoyé par le serveur.
POST /resources HTTP/1.1
Peut-onseulementêtre exécuté avec PUT de la manière suivante:
METTRE
Met à jour la ressource avecexistingResourceIdcomme identifiant, sous l'URI/resources oucollection.
PUT /resources/<existingResourceId> HTTP/1.1
Lorsque vous utilisez REST et l'URI en général, vous avezgenericsur leleftetspecificsur leright. Lesgénériquessont généralement appeléscollectionset les éléments plusspécifiquespeuvent être appelésressource. Notez qu'unresourcepeut contenir uncollection.
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 êtestoujoursen référence à uncollection, donc chaque fois que vous dites:
POST /users HTTP/1.1
vous publiez un nouvel utilisateur surutilisateurscollection.
Si vous continuez et essayez quelque chose comme ça:
POST /users/john HTTP/1.1
cela fonctionnera, mais sémantiquement vous dites que vous voulez ajouter une ressource aujohncollectionsous leutilisateurscollection.
Une fois que vous utilisez PUT, vous vous référez à unresourceou à un seul élément, éventuellement dans uncollection. 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, lejohnresourcesous leutilisateurscollection.
Permettez-moi de souligner certaines parties importantes de la spécification:
La méthodePOSTest utilisée pour demander au serveur d’origineaccepterl’entité incluse dans la demande en tant quenewsubordonnéde la ressource identifiée par l'URI de la requête dans la ligne de la requête
Par conséquent, crée un nouveauressourcesur uncollection.
La méthodePUT/ demande que l'entité incluse soitstockéesous l'URI de demande fourni. Si l'URI de la demande fait référence à une ressourcedéjà existante, l'entité incluse DEVRAIT être considérée comme une versionmodifiéede celle résidant sur le serveur d'origine. Si l'URI de la demande ne pointe pasvers une ressource existante, et que l'URI estcapabled'être défini comme unnewresourcepar l'agent utilisateur demandeur, le serveur d'origine peutcreatela ressource avec cet URI. "
Par conséquent, créez ou mettez à jour en fonction de l'existence duresource.
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 à example.com/users puisque vous ne connaissez pas encore l'URL de l'utilisateur, vous souhaitez que le serveur le crée.
Vous PUT à 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 ainsi que Ruby sur Rails le fait, de toute façon.
PUT /items/1 #=> update
POST /items #=> create
Les deux sont utilisés pour la transmission de données entre client et serveur, mais ils présentent des différences subtiles, à savoir:
Analogie:
Analogie avec les réseaux sociaux:
REST est un concept de haut niveau très . En fait, il ne parle même pas du tout de HTTP!
Si vous avez des doutes sur la manière d'implémenter REST dans HTTP, vous pouvez toujours consulter la spécification Atom Publication Protocol (AtomPub) . AtomPub est un standard d'écriture de services Web RESTful avec HTTP, développé par de nombreux luminaires HTTP et REST, avec les contributions de Roy Fielding, l'inventeur de REST et le (co) inventeur de HTTP lui-même.
En fait, vous pourrez même utiliser directement AtomPub. Bien qu’il soit issu de la communauté des blogueurs, il n’est en aucun cas limité aux blogs: il s’agit d’un protocole générique pour l’interaction REST avec des collections arbitraires (imbriquées) de ressources arbitraires via HTTP. Si vous pouvez représenter votre application sous la forme d'une collection imbriquée de ressources, vous pouvez simplement utiliser AtomPub sans vous soucier de l'utilisation de PUT ou POST, des codes d'état HTTP à renvoyer et de tous ces détails.
Voici ce que AtomPub a à dire sur la création de ressources (section 9.2):
Pour ajouter des membres à une collection, les clients envoient POST demandes à l'URI de la collection.
La décision d'utiliser PUT ou POST pour créer une ressource sur un serveur avec une API HTTP + REST dépend de l'identité de l'utilisateur propriétaire de l'URL. Si le client connaît ou participe à la définition de la structure d’URL, il s’agit d’un couplage inutile, qui s'apparente aux couplages indésirables résultant de la SOA. Les types de couplage qui s’échappent sont la raison pour laquelle REST est si populaire. Par conséquent la méthode appropriée à utiliser est POST. Il existe des exceptions à cette règle qui se produisent lorsque le client souhaite conserver le contrôle de la structure d'emplacement du les ressources qu'il déploie. Ceci est rare et signifie probablement que quelque chose ne va pas.
À ce stade, certaines personnes diront que si les 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 sur 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. [Un échec 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 RESTful-URL 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. éviter les couplages. Si cela vous rend confus, vous en apprendrez davantage sur l’importance de la découverte de soi dans la conception des API.
L'utilisation de POST pour créer des ressources est soumise à une considération de conception, car POST n'est pas idempotent. Cela signifie que Un POST plusieurs fois ne garantit pas le même comportement à chaque fois. Cela fait peur aux gens qui utilisent PUT pour créer des ressources alors qu'ils ne le devraient pas. Ils savent que c'est faux (le POST est pour CREATE), mais ils le font quand même sais pas comment résoudre ce problème. Cette préoccupation est démontrée dans la situation suivante:
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 soumettre à nouveau 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 bon recours car :
Mise à jour basée sur la publication de la RFC 7231 pour remplacer 2616
RFC 7231 est conçu pour remplacer 2616 et in Section 4.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 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 au cas où un POST se répète. Cependant, le contraire est vrai. Renvoyer un 303 n'aurait 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 POST ne doit pas être idempotent et continue de maintenir que POST devrait être utilisé pour la création.
Pour plus d'informations à ce sujet, lisez ceci article .
J'aime ce conseil, de définition de PUT dans la RFC 2616 :
La différence fondamentale entre les demandes 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 ici, que PUT est mieux appliqué aux ressources qui ont déjà un nom, et que POST est utile 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:
En bref:
PUT est idempotent, l'état de la ressource sera le même si la même opération est exécutée une fois ou plusieurs fois.
POST est non idempotent, l'état de la ressource pouvant devenir différent si l'opération est exécutée plusieurs fois par rapport à l'exécution d'une seule fois.
PUT Vous pouvez penser à semblable à "MISE À JOUR SET SET ÉTUDIANT =" abc "où id =" 123 ";
POST Vous pouvez penser à quelque chose comme "INSERT INTO STUDENT (nom, adresse) VALUES (" abc "," xyzzz ");
L'étudiant est généré automatiquement.
Avec PUT, si la même requête est exécutée plusieurs fois ou une fois, l'état de la table STUDENT reste identique.
Dans le cas de POST, si la même requête est exécutée plusieurs fois, plusieurs enregistrements Student sont créés dans la base de données et l'état de la base de données change à chaque exécution d'une requête "INSERT".
NOTE: PUT a besoin d'un emplacement de ressource (déjà ressource) sur lequel la mise à jour doit avoir lieu, alors que POST ne nécessite pas cela. Donc intuitivement, POST est destiné à la création d'une nouvelle ressource, alors que PUT est nécessaire à la mise à jour de la ressource existante.
Certains peuvent penser que des mises à jour peuvent être effectuées avec POST. Il n'y a pas de règle stricte à utiliser pour les mises à jour ou à utiliser pour créer. Encore une fois, ce sont des conventions, et intuitivement, je suis enclin à suivre le raisonnement mentionné ci-dessus et je le suis.
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 QUEUE 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. 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.
Nouvelle réponse (maintenant que j'ai compris REST meilleur):
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 le serveur doit savoir comment identifier ce contenu.
PUT x
(si x
identifie un ressource ): "Remplace le contenu de la ressource identifiée par x
par mon contenu."
PUT x
(si x
n'identifie pas une ressource): "Créez une nouvelle ressource contenant mon contenu et utilisez x
pour 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é à un autre contenu). Cette ressource doit être identique ou subordonnée à celle qui x
identifie. " "La ressource de ( y est subordonnée à la ressource de ) x " est généralement mais pas nécessairement implémentée en faisant y un sous-chemin de x (par exemple x = /foo
et y = /foo/bar
) et modification de la ou des représentations de la ressource x pour refléter l'existence d'une nouvelle ressource, par exemple avec un hyperlien vers la ressource de y 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é tilisez hypermédia au lieu de la construction d’URL côté client pour parcourir 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 consiste généralement en des lignes associé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. convertir une charge JSON en instructions SQL.
Réponse originale (pourrait être plus facile à lire) :
PUT /something
(si /something
existe déjà): "Prenez tout ce que vous avez sur /something
et remplacez-le par ce que je vous ai donné."
PUT /something
(si /something
n'existe pas déjà): "Prenez ce que je vous ai donné et mettez-le à /something
."
POST /something
: "Prenez ce que je vous ai donné et mettez-le où vous voulez sous /something
tant que vous me donnez son URL lorsque vous avez terminé."
Réponse courte:
Règle simple: utilisez POST pour créer, utilisez PUT pour mettre à jour.
Réponse longue:
POSTER:
METTRE:
Réponse plus longue:
Pour le comprendre, nous devons nous demander pourquoi PUT était nécessaire, quels étaient les problèmes que PUT essayait de résoudre et que POST ne pouvait pas.
Du point de vue de l'architecture REST, il n'y en a aucun qui compte. Nous aurions pu vivre sans PUT aussi. Mais du point de vue du développeur client, cela simplifiait grandement sa vie.
Avant PUT, les clients ne savaient pas directement l'URL générée par le serveur ou si tout avait été généré, ni si les données à envoyer au serveur étaient déjà mises à jour ou non. PUT a soulagé le développeur de tous ces maux de tête. PUT est idempotent, PUT gère les conditions de concurrence et PUT permet au client de choisir l'URL.
Ruby sur 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. POST est déjà utilisé, mais sans grande interopérabilité (il n'existe pas de 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.
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 URL finira par être, lors de la création d'une ressource. Donc une partie du choix entre PUT et POST va être à peu près combien vous pouvez faire confiance au client pour fournir correct, normalisé URL cohérents avec votre schéma d'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.
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 parce que la méthode POST est non 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. *
En une seule ligne, utilisez POST pour ajouter ne nouvelle entrée dans la base de données et PUT à pdate = quelque chose dans la base de données.
La considération la plus importante est fiabilité. Si un message POST est perdu, l'état du système n'est pas défini. La récupération automatique est impossible. Pour les messages PUT, l'état n'est défini que jusqu'à la première tentative réussie.
Par exemple, il peut ne pas être une bonne idée de créer des transactions par carte de crédit avec POST.
Si vous avez des URI générés automatiquement sur votre ressource, vous pouvez toujours utiliser PUT en transmettant un URI généré (pointant sur une ressource vide) au client.
Quelques autres considérations:
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 était en 2000. Qu'avons-nous 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 avant de revenir. Dans ces conditions, émettre des demandes PUT, POST et DELETE directement contre des ressources importantes 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 passer d’un cadre à l’autre pour utiliser PUT au lieu de POST, puis d’autres pour créer un certain type d’erreur sur le serveur si vous détectez des demandes en double. De retour chez le client, vous devez ensuite sauter dans les cerceaux 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 pour un seul utilisateur (appelons-les des actions). Les clients demandent une nouvelle "action" sur une ressource substantive avec un POST vide pour la ressource. POST ne sera utilisé que pour cela. Une fois en possession de l’URI de l’action nouvellement créée, le client PUT la demande non sécurisée à l’URI de l’action et non de 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 effectue l'activité, 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 similarité 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 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 tels, 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 en une force :-)
Avant de me dire que cela 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 peu de changement dans la 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: 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.
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 dans form-data
Dans la méthode PUT vous devez envoyer les paramètres du corps dans x-www-form-urlencoded
En-tê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
EDIT
Le type de contenu "application/x-www-form-urlencoded" est inefficace pour l'envoi 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
Il semble toujours y avoir une certaine confusion quant au moment d'utiliser le protocole 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 R(etrieve) et D(elete) des opérations CRUD peuvent être mappés directement aux méthodes HTTP GET et DELETE, respectivement. Cependant, la confusion réside dans les opérations C(reate) et U(update). 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 retourner 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 utilisation de la méthode HTTP PUT et de la méthode HTTP POST pour REST services 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 corrélez pas et ne mappez pas directement 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 devrait ê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.
le serveur d'origine peut créer la ressource avec cet URI
Donc, vous utilisez POST et probablement, mais pas nécessaire, PUT pour la création de ressources. Vous n'êtes pas obligé de supporter les deux. Pour moi, POST est parfaitement suffisant. C'est donc une décision de conception.
Comme votre citation l'a mentionné, vous utilisez PUT pour la création. Aucune ressource n'est affectée à un IRI et vous souhaitez néanmoins créer une ressource. Par exemple, PUT /users/123/password
remplace 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).
Je vais atterrir avec ce qui suit:
PUT fait référence à une ressource identifiée par l'URI. Dans ce cas, vous le mettez à jour. C'est la partie des trois verbes faisant référence aux ressources - supprimer et devenir les deux autres.
POST est fondamentalement un message de forme libre, dont le sens est défini comme "hors bande". Si le message peut être interprété comme ajoutant une ressource à un répertoire, ce serait OK, mais vous devez comprendre le message que vous envoyez (publication) pour savoir ce qui se passera avec la ressource.
Etant donné que PUT, GET et DELETE font référence à une ressource, elles sont également, par définition, idempotentes.
POST peut exécuter les trois autres fonctions, mais la sémantique de la demande sera alors perdue pour les intermédiaires tels que les caches et les proxies. Cela s'applique également à la sécurisation de la ressource, car l'URI d'une publication n'indique pas nécessairement la ressource à laquelle elle s'applique (elle peut cependant).
Un PUT n'a pas besoin d'être une création; le service peut générer une erreur si la ressource n'est pas déjà créée, sinon mettez-la à jour. Ou vice versa - cela peut créer la ressource, mais pas autoriser les mises à jour. La seule chose requise à propos de PUT est qu’elle pointe vers une ressource spécifique et que sa charge utile soit la représentation de cette ressource. Un PUT réussi signifie (à moins d'interférence) qu'un GET va récupérer la même ressource.
Edit: Une dernière chose - un PUT peut créer, mais s'il le fait, l'ID doit être un ID naturel - AKA une adresse électronique. De cette façon, lorsque vous mettez deux fois, la deuxième est une mise à jour de la première. Cela le rend idempotent.
Si l'ID est généré (un nouvel ID d'employé, par exemple), le second PUT avec la même URL créera un nouvel enregistrement, qui violera la règle idempotent. Dans ce cas, le verbe serait POST et le message (pas ressource) consisterait à créer une ressource en utilisant les valeurs définies dans ce message.
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 demande de PUT exacte plusieurs fois et le résultat sera comme si vous ne l'aviez exécutée qu'une seule 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 POST sur une ressource située à une URL particulière, vous publiez souvent des informations connexes 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 voulez POST un message destiné à un flux existant, vous POST 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.
La plupart du temps, vous les utiliserez comme ceci:
Par exemple:
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, il créera 3 objets), mais PUT sera idempotent (si vous l'appelez 3 fois, le résultat sera le même). . PUT est souvent utilisé pour l'opération "upsert" (créer ou mettre à 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 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 mettre à jour uniquement les ressources existantes et modifier 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, je ne m'inquiète pas beaucoup dans la mesure où 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 directives permettant de garder votre API simple. Si vous vous retrouvez avec une solution de contournement compliquée juste pour cocher la case "RESTfull", alors vous échouez dans le but;)
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 (tirés de la documentation de l'API Microsoft): http://www.asp.net/web-api/overview/creating-web-apis/creating -a-web-api-that-support-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.
Voici une règle simple:
PUT à une URL doit être utilisé pour mettre à jour ou créer la ressource pouvant être située à cette URL.
POST vers 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.
Si vous connaissez les opérations de base de données, il y a
J'utilise PUT
pour les opérations de fusion et de mise à jour et utilise POST
pour les insertions.
En pratique, POST fonctionne bien pour la création de ressources. L'URL de la ressource nouvellement créée doit être renvoyée dans l'en-tête de réponse Location. PUT doit être utilisé pour mettre à jour complètement une ressource. Veuillez comprendre que ce sont les meilleures pratiques lors de la conception d'une API RESTful. La spécification HTTP en tant que telle ne restreint pas l'utilisation de PUT/POST avec quelques restrictions pour la création/mise à jour de ressources. Jetez un œil à http://techoctave.com/c7/posts/71-Twitter-rest-api-dissected qui résume les meilleures pratiques.
POST: Utilisez-le pour créer de nouvelles ressources. C'est comme INSERT (instruction SQL) avec un ID auto-incrémenté. Dans la partie réponse, il contient un nouvel identifiant généré.
POST est également utilisé pour mettre à jour un enregistrement.
PUT: Utilisez-le pour créer une nouvelle ressource, mais je connais ici la clé d'identité. C'est comme INSERT (instruction SQL) où je connais d'avance la clé d'identité. Dans la partie réponse, il n'envoie rien.
PUT est également utilisé pour mettre à jour une ressource
Alors, lequel devrait être utilisé pour créer une ressource? Ou faut-il supporter les deux?
Vous devriez utiliser PATCH
. Vous PATCH la liste des questions comme
PATCH /questions HTTP/1.1
avec une liste contenant votre objet à créer comme
[
{
"title": "I said semantics!",
"content": "Is this serious?",
"answer": "Not really"
}
]
C'est une requête PATCH en tant que
id
).Un des grands avantages de cette méthode est que vous pouvez créer plusieurs entités à l’aide d’une seule demande, simplement en les fournissant toutes dans la liste.
C'est quelque chose que PUT
ne peut évidemment pas. Vous pouvez utiliser POST
pour créer plusieurs entités car il s'agit de l'évier de cuisine de HTTP et peut pratiquement tout faire.
Un inconvénient est que probablement personne n'utilise PATCH
de cette façon. J'ai peur, je viens de l'inventer, mais j'espère que j'ai fourni une bonne argumentation.
Vous pouvez utiliser CREATE
à la place, les verbes HTTP personnalisés étant autorisés, ils risquent toutefois de ne pas fonctionner avec certains outils.
En ce qui concerne la sémantique, CREATE
est le seul choix qui s'impose, tout le reste est un piquet carré dans un trou rond. Malheureusement, tout ce que nous avons sont des trous ronds.
Je pense qu’il ya aussi un point intéressant qui n’a pas été partagé sur cette question PUT vs POST:
Si vous souhaitez avoir une application Web qui fonctionne sans JavaScript (par exemple, si quelqu'un utilise un navigateur de ligne de commande tel que Lynx ou un module complémentaire de navigateur tel que NoScript ou uMatrix), vous devrez utiliser POST pour envoyer. les données car les formulaires HTML ne prennent en charge que les requêtes GET et POST HTTP.
En gros, si vous souhaitez utiliser l'amélioration progressive ( https://en.wikipedia.org/wiki/Progressive_enhancement ) pour que votre application Web fonctionne partout, avec ou sans JavaScript, vous ne pouvez pas utiliser d'autres méthodes HTTP telles que PUT ou DELETE, qui ont été ajoutés uniquement dans HTTP version 1.1.