6374 votes

Quelle est la différence entre POST et PUT dans le protocole HTTP ?

Según RFC 2616, § 9.5 , POST est utilisé pour créer une ressource :

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.

Según RFC 2616, § 9.6 , PUT est utilisé pour créer ou remplacer une ressource :

La méthode PUT demande que l'entité jointe soit stockée sous l'URL de la demande fournie. Si la Request-URI fait référence à une ressource déjà existante, l'entité jointe DOIT être considérée comme une version modifiée de celle qui réside sur le serveur d'origine. Si la Request-URI ne renvoie pas à une ressource existante, et que cette URI peut être définie comme une nouvelle ressource par l'agent utilisateur demandeur, le serveur d'origine peut créer la ressource avec cette URI.

Alors, quelle méthode HTTP doit être utilisée pour créer une ressource ? Ou les deux doivent-elles être prises en charge ?

67 votes

Il peut être utile d'utiliser les définitions de HTTPbis - Roy a fait un travail considérable pour les clarifier. Voir : tools.ietf.org/html/

20 votes

Afin d'adapter le commentaire de @MarkNottingham à la dernière révision, voici ce qui suit POST y PUT comme défini sur HTTPbis.

49 votes

Il me semble que ce débat est né de la pratique courante consistant à simplifier à l'extrême REST en décrivant les méthodes HTTP en termes d'opérations CRUD.

4918voto

Brian R. Bondy Points 141769

Dans l'ensemble :

PUT et POST peuvent tous deux être utilisés pour la création.

Vous devez vous demander "sur quoi porte l'action ?", pour distinguer ce que vous devez utiliser. Supposons que vous conceviez une API pour poser des questions. Si vous voulez utiliser POST, vous le ferez sur une liste de questions. Si vous voulez utiliser PUT, vous le ferez pour une question particulière.

Super, les deux peuvent être utilisés, alors lequel dois-je utiliser dans ma conception RESTful :

Il n'est pas nécessaire de prendre en charge à la fois PUT et POST.

C'est à vous de décider lequel vous utilisez. Mais n'oubliez pas d'utiliser le bon en fonction de l'objet auquel vous faites référence dans la requête.

Quelques considérations :

  • Nommez-vous les objets URL que vous créez explicitement, ou laissez-vous le serveur décider ? Si vous les nommez, utilisez PUT. Si vous laissez le serveur décider, utilisez POST.
  • PUT est défini de manière à supposer l'idempotence, donc si vous PUT un objet deux fois, cela ne devrait avoir aucun effet supplémentaire. C'est une propriété intéressante, c'est pourquoi j'utiliserais PUT lorsque cela est possible. Assurez-vous simplement que l'idempotence de PUT est correctement implémentée dans le serveur.
  • Vous pouvez mettre à jour ou créer une ressource avec PUT avec la même URL d'objet.
  • Avec POST, deux requêtes peuvent arriver en même temps pour modifier une URL, et elles peuvent mettre à jour différentes parties de l'objet.

Un exemple :

J'ai écrit ce qui suit dans le cadre de 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 la créer tout en spécifiant le nom. Cela devrait une erreur "ressource non trouvée" car car <new_question> n'existe pas encore. Vous devez mettre le <new_question> sur le serveur en premier.

Vous pouvez cependant faire quelque chose comme ceci pour créer une ressource 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é, les nouveaux objets vous sera renvoyé.

PUT :

Utilisé pour créer une ressource, ou l'écraser. Alors que vous spécifiez la nouvelle URL de la ressource.

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/

En outre, et de manière un peu plus concise, RFC 7231 Section 4.3.4 PUT (c'est nous qui soulignons),

4.3.4. PUT

La méthode PUT demande que l'état de la ressource cible soit created o replaced avec l'état défini par la représentation incluse dans les données utiles du message de demande.

1230 votes

Je pense qu'on n'insistera jamais assez sur le fait que PUT est idempotent : si le réseau est défaillant et que le client n'est pas sûr que sa requête ait été acceptée, il peut simplement l'envoyer une seconde (ou 100ème) fois, et la spécification HTTP garantit que cela a exactement le même effet que l'envoi unique.

91 votes

@Jörg W Mittag : Ce n'est pas nécessaire. La deuxième fois pourrait renvoyer un conflit 409 ou autre si la demande a été modifiée entre-temps (par un autre utilisateur ou par la première demande elle-même, qui est passée).

2 votes

Je pense qu'il n'y a pas de différence dans la définition. Le conflit 409 pourrait être un résultat même pour la première demande faite par le client. Dans tous les cas, il devrait étudier le problème.

2600voto

Cheeso Points 87022

Vous pouvez trouver des affirmations sur le web qui disent que

Ni l'un ni l'autre n'est tout à fait juste.


Il est préférable de choisir entre PUT et POST en se basant sur les critères suivants idempotence de l'action.

PUT implique de mettre une ressource - en remplaçant complètement ce qui est disponible à l'URL donnée par quelque chose de 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, qu'elle existe déjà ou non (par exemple, pour créer ou mettre à jour) !

POST met à jour une ressource, ajoute une ressource subsidiaire ou provoque un changement. Un POST n'est pas idempotent, de la même façon qu'un 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 pour la catégorie de choses que vous voulez créer.

donc :

POST /expense-report

ou :

PUT  /expense-report/10929

87 votes

Je suis d'accord, dès que l'idempotence est concernée, elle devrait l'emporter sur toute autre préoccupation, car se tromper peut provoquer de nombreux bugs inattendus.

2 votes

Oui. En fait, le protocole AtomPub défie cela (ou plus exactement, restreint sa signification sémantique de PUT) : "PUT est utilisé pour modifier une ressource connue. Il n'est pas utilisé pour la création de Ressources". Ce n'est pas parce que le protocole AtomPub le dit (qui est d'ailleurs valide) que tous les protocoles RESTful doivent le suivre. (parce que REST est générique)

21 votes

Si POST peut mettre à jour une ressource, comment cela peut-il ne pas être idempotent ? Si je change l'âge d'un étudiant en utilisant PUT et que je le fais 10x fois, l'âge de l'étudiant est le même que si je l'avais fait une fois.

854voto

Nigel Thorne Points 6412
  • POST à une URL crée une ressource enfant à un serveur défini URL.
  • PUT à une URL crée/remplace la ressource dans son intégralité à l'adresse suivante client défini URL.
  • PATCH à une URL mises à jour partie de la ressource à cette URL définie par le client.

La spécification pertinente pour PUT et POST est la suivante RFC 2616 §9.5 et suivants.

POST crée une ressource enfant alors POST à /items crée une ressource qui vit sous le /items ressource. Par exemple. /items/1 . En envoyant deux fois le même paquet de courrier, on crée deux ressources.

PUT sert à créer ou à remplacer une ressource à un URL connue par le client .

Par conséquent : PUT n'est un candidat pour CREATE que lorsque 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à, donc envoyer deux fois la même requête n'a aucun effet. En d'autres termes, les appels à PUT sont idempotents .

Le RFC se lit comme suit :

La différence fondamentale entre les demandes POST et PUT se reflète dans la signification différente de la Request-URI. L'URI d'une requête POST identifie la ressource qui traitera l'entité jointe. Cette ressource peut être un processus d'acceptation des données, une passerelle vers un autre protocole ou une entité distincte qui accepte les annotations. En revanche, l'URI d'une demande PUT identifie l'entité jointe à la demande - l'agent utilisateur sait quelle URI est visée 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,

Nota: PUT a surtout été utilisé pour mettre à jour des ressources (en les remplaçant dans leur intégralité), mais depuis peu, on s'oriente vers l'utilisation de PATCH pour la mise à jour de ressources existantes, car PUT spécifie qu'il remplace la ressource entière. RFC 5789.

Mise à jour 2018 : Il y a un cas qui peut être fait pour éviter PUT. Voir "REST sans PUT"

Avec la technique "REST sans PUT", l'idée est que les consommateurs sont obligés de poster de nouvelles ressources de demande "nounifiées". Comme nous l'avons vu précédemment, le changement d'adresse postale d'un client est un POST vers une nouvelle ressource "ChangeOfAddress", et non pas un PUT d'une ressource "Customer" avec une avec une valeur de champ d'adresse postale différente.

tiré de Conception d'API REST - Modélisation des ressources par Prakash Subramaniam de Thoughtworks

Cela oblige l'API à éviter les problèmes de transition d'état avec de multiples clients mettant à jour une seule ressource, et s'accorde mieux avec le sourcing d'événements et CQRS. Lorsque le travail est effectué de manière asynchrone, le fait de POSTER la transformation et d'attendre qu'elle soit appliquée semble approprié.

71 votes

Ou de l'autre côté de la barrière : PUT si le client détermine l'adresse de la ressource résultante, POST si le serveur le fait.

4 votes

Je pense que cette réponse devrait être modifiée pour rendre plus clair ce que @DanMan a indiqué de manière très simple. Ce que je trouve le plus précieux ici, c'est la note à la fin, indiquant qu'un PUT doit être utilisé uniquement pour remplacer la ressource entière.

4 votes

PATCH n'est pas une option réaliste pour au moins quelques années, mais je suis d'accord avec l'idéologie.

337voto

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 de l'utilisateur 5".

Usted POST à exemple.com/utilisateurs puisque vous ne connaissez pas le URL de l'utilisateur, vous voulez que le serveur le crée.

Usted PUT à example.com/users/id puisque vous voulez remplacer/créer une spécifique utilisateur.

POSTer deux fois avec les mêmes données revient à créer deux utilisateurs identiques avec des identifiants différents. PUTer deux fois avec les mêmes données crée l'utilisateur la première fois et le met dans le même état la deuxième fois (pas de changement). Puisque vous vous retrouvez avec le même état après une requête PUT quel que soit le nombre de fois où vous l'exécutez, on dit qu'elle est "aussi puissante" à chaque fois - idempotente. C'est utile pour relancer automatiquement les demandes. Il n'y a plus de "vous êtes sûr de vouloir renvoyer" lorsque vous appuyez sur le bouton "retour" du navigateur.

Un conseil général est d'utiliser POST quand vous avez besoin que le serveur ait le contrôle de URL génération de vos ressources. Utilisez PUT autrement. Préférez PUT sur POST .

30 votes

Par négligence, on a peut-être appris qu'il n'y a que deux verbes à utiliser : GET et POST. GET pour obtenir, POST pour modifier. Même PUT et DELETE étaient exécutés en utilisant POST. Le fait de demander ce que signifie réellement PUT 25 ans plus tard est peut-être le signe que nous avons mal appris au départ. La popularité de REST a ramené les gens à l'essentiel et nous devons maintenant désapprendre les mauvaises erreurs du passé. POST a été surutilisé et est maintenant couramment enseigné de manière incorrecte. La meilleure partie : "POSTing twice with the same data means create two identical [resources]". Excellente remarque !

2 votes

Comment pouvez-vous utiliser PUT pour créer un enregistrement par l'ID, comme dans votre exemple user 5 s'il n'existe pas encore ? Ne voulez-vous pas dire update, replace if already exists ? ou quelque chose comme ça

0 votes

@Coulton : Je pensais ce que j'ai écrit. Vous insérez l'utilisateur 5 si vous faites un PUT vers /users/5 et que #5 n'existe pas encore.

193voto

ThaDon Points 2609

J'aimerais ajouter mon conseil "pragmatique". Utilisez PUT lorsque vous connaissez l'"id" par lequel l'objet que vous sauvegardez peut être récupéré. L'utilisation de PUT ne fonctionnera pas très bien si vous avez besoin, par exemple, qu'un identifiant généré par une base de données soit renvoyé pour que vous puissiez effectuer des recherches ou des mises à jour ultérieures.

Ainsi : Pour sauvegarder un utilisateur existant, ou un utilisateur pour lequel le client génère l'identifiant et il a été vérifié 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 mettre à jour l'objet :

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

20 votes

En fait, cela devrait être POST /users . (Notez que /users est au pluriel). Cela a pour effet de créer un nouvel utilisateur et d'en faire une ressource enfant de la ressource /users collection.

6 votes

@DavidRR pour être juste, la façon de gérer les groupes est un tout autre débat. GET /users a du sens, ça se lit comme tu veux, mais je serais d'accord avec GET /user/<id> o POST /user (avec une charge utile pour ledit nouvel utilisateur) parce qu'il se lit correctement 'get me users 5' est bizarre, mais 'get me user 5' est plus naturel. Je serais probablement toujours du côté de la pluralisation cependant :)

4 votes

@thecoshman Vous pouvez le lire comme "les utilisateurs me donnent l'identifiant 5" ;)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X