Die Entscheidung, ob PUT oder POST verwendet werden soll, um eine Ressource auf einem Server mit einer HTTP- und REST-API zu erstellen, basiert darauf, wer die URL-Struktur besitzt. Wenn der Client die URL-Struktur kennt oder an deren Definition teilnimmt, handelt es sich um eine unnötige Kopplung, die ähnlich den unerwünschten Kopplungen ist, die sich aus SOA ergeben sind. Das Vermeiden von bestimmten Arten von Kopplungen ist der Grund, warum REST so beliebt ist. Daher ist die richtige Methode, POST zu verwenden. Es gibt Ausnahmen von dieser Regel, die auftreten, wenn der Client die Kontrolle über die Struktur der Ressourcen, die er bereitstellt, behalten möchte. Dies ist selten und deutet wahrscheinlich darauf hin, dass etwas anderes falsch ist.
An diesem Punkt werden einige argumentieren, dass bei Verwendung von RESTful-URLs der Client die URL der Ressource kennt und daher ein PUT akzeptabel ist. Schließlich ist dies der Grund, warum kanonische, normalisierte, Ruby on Rails-, Django-URLs wichtig sind, schau dir die Twitter-API an ... blah blah blah. Diese Leute müssen verstehen, dass es keine RESTful-URL gibt und dass Roy Fielding selbst erklärt hat, dass:
Eine REST-API darf keine festen Ressourcennamen oder Hierarchien definieren (eine offensichtliche Kopplung von Client und Server). Server müssen die Freiheit haben, ihren eigenen Namensraum zu kontrollieren. Erlauben Sie stattdessen Servern, Clients anzuweisen, wie sie passende URIs konstruieren können, dies wird in HTML-Formularen und URI-Vorlagen getan, indem diese Anweisungen innerhalb von Medientypen und Linkbeziehungen definiert werden. [Ein Scheitern hier impliziert, dass Clients aufgrund von außerhalb bereitgestellten Informationen, wie einem domänenspezifischen Standard, eine Ressourcenstruktur annehmen, die das datenorientierte Äquivalent zur funktionalen Kopplung von RPC darstellt].
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
Die Idee einer RESTful-URL ist tatsächlich eine Verletzung von REST, da der Server für die URL-Struktur zuständig ist und frei entscheiden sollte, wie sie verwendet wird, um Kopplungen zu vermeiden. Wenn dich das verwirrt, lies über die Bedeutung der Selbstdarstellung bei der API-Entwicklung.
Die Verwendung von POST zur Erstellung von Ressourcen erfordert eine Designüberlegung, da POST nicht idempotent ist. Dies bedeutet, dass das wiederholte Durchführen eines POST nicht bei jeder Ausführung das gleiche Verhalten garantiert. Dies verunsichert die Leute, die PUT zur Erstellung von Ressourcen verwenden, wenn sie das nicht sollten. Sie wissen, dass es falsch ist (POST ist für ERSTELLEN), aber sie tun es trotzdem, weil sie nicht wissen, wie sie dieses Problem lösen sollen. Dieses Anliegen wird in folgender Situation demonstriert:
- Der Client sendet eine neue Ressource an den Server.
- Der Server verarbeitet die Anfrage und sendet eine Antwort zurück.
- Der Client erhält die Antwort nie.
- Der Server ist sich nicht bewusst, dass der Client die Antwort nicht erhalten hat.
- Der Client hat keine URL für die Ressource (deshalb ist PUT keine Option) und wiederholt den POST.
- POST ist nicht idempotent und der Server …
Schritt 6 ist der Punkt, an dem die Leute oft verwirrt sind, was zu tun ist. Es gibt jedoch keinen Grund, eine Notlösung zu schaffen, um dieses Problem zu lösen. Stattdessen kann HTTP gemäß RFC 2616 verwendet werden und der Server antwortet:
10.4.10 409 Konflikt
Die Anforderung konnte aufgrund eines Konflikts mit dem aktuellen Status der Ressource nicht abgeschlossen werden. Dieser Code ist nur in Situationen erlaubt, in denen erwartet wird, dass der Benutzer den Konflikt lösen und die Anfrage erneut senden kann. Der Antworttext SOLL ausreichend
Informationen enthalten, damit der Benutzer die Quelle des Konflikts erkennen kann. Idealerweise würde die Antwort-Entität ausreichend Informationen für den Benutzer oder das Benutzeragenten enthalten, um das Problem zu beheben; das ist jedoch möglicherweise nicht möglich und nicht erforderlich.
Konflikte treten höchstwahrscheinlich als Reaktion auf eine PUT-Anforderung auf. Zum Beispiel, wenn eine Versionierung verwendet wird und die Entität, die PUT enthalten ist, Änderungen an einer Ressource enthält, die im Konflikt mit denjenigen steht, die von einem früheren (Drittanbieter-) Anforderung, könnte der Server die Antwort mit 409 verwenden, um anzuzeigen, dass es die Anforderung nicht abschließen kann. In diesem Fall würde die Antwort-Entität wahrscheinlich eine Liste der Unterschiede zwischen erhalten die beiden Versionen in einem vom Antwort-Typ definierten Format.
Die Antwort mit einem Statuscode von 409 Conflict ist der richtige Weg, weil:
- Das Durchführen eines POST von Daten, die eine ID enthalten, die mit einer bereits im System vorhandenen Ressource übereinstimmt, ist "ein Konflikt mit dem aktuellen Status der Ressource."
- Da das Wichtigste darin besteht, dass der Client versteht, dass der Server die Ressource hat und angemessene Maßnahmen ergreifen kann. Dies ist eine "Situation(en), in der erwartet wird, dass der Benutzer den Konflikt lösen und die Anfrage erneut senden kann."
- Eine Antwort, die die URL der Ressource mit der konkurrierenden ID und die geeigneten Voraussetzungen für die Ressource enthält, würde "ausreichend Informationen für den Benutzer oder das Benutzeragenten enthalten, um das Problem zu beheben", was der ideale Fall gemäß RFC 2616 ist.
Update aufgrund der Veröffentlichung von RFC 7231 zur Ersetzung von 2616
RFC 7231 ist darauf ausgelegt, 2616 zu ersetzen, und in Abschnitt 4.3.3 werden mögliche Antworten für ein POST beschrieben
Wenn das Ergebnis der Verarbeitung eines POST einer Darstellung einer bereits vorhandenen Ressource entsprechen würde, kann ein Ursprungsserver den Benutzeragenten zu dieser Ressource umleiten, indem er eine 303 (Siehe Andere) Antwort mit der Kennung der vorhandenen Ressource im Feld Location sendet. Dies bietet dem Benutzeragenten den Vorteil, eine Ressourcenkennung zu erhalten und die Darstellung über eine Methode zu übertragen, die sich besser für gemeinsames Caching eignet, jedoch auf Kosten einer zusätzlichen Anfrage, wenn der Benutzeragent die Darstellung nicht bereits im Cache hat.
Es mag nun verlockend sein, einfach eine 303 zurückzugeben, wenn ein POST wiederholt wird. Das Gegenteil ist jedoch der Fall. Das Zurückgeben eines 303 würde nur Sinn ergeben, wenn mehrere Erstellungsanforderungen (Erstellen verschiedener Ressourcen) denselben Inhalt zurückgeben. Ein Beispiel wäre eine "Danke für die Einreichung Ihrer Anfrage" Nachricht, die der Client nicht jedes Mal neu herunterladen muss. RFC 7231 behauptet weiterhin in Abschnitt 4.2.2, dass POST nicht idempotent sein soll, und besteht darauf, dass POST für die Erstellung verwendet werden soll.
Weitere Informationen hierzu finden Sie in diesem Artikel.
66 Stimmen
Es kann hilfreich sein, die Definitionen in HTTPbis zu verwenden - Roy hat sich viel Arbeit gemacht, um sie zu klären. Siehe: tools.ietf.org/html/…
19 Stimmen
Nur um den Kommentar von @MarkNottingham auf den neuesten Stand zu bringen, hier sind POST und PUT, wie sie auf HTTPbis definiert sind.
48 Stimmen
Es scheint mir, dass dieser Diskurs aus der gängigen Praxis entstanden ist, REST durch die Beschreibung der HTTP-Methoden in Bezug auf CRUD-Operationen zu vereinfachen.
7 Stimmen
Leider sind die ersten Antworten zu POST falsch. Überprüfen Sie meine Antwort für eine bessere Erklärung der Unterschiede: stackoverflow.com/a/18243587/2458234
35 Stimmen
PUT und POST sind beide unsichere Methoden. PUT ist jedoch idempotent, während POST es nicht ist. - Weitere Informationen finden Sie unter: restcookbook.com/HTTP%20Methods/put-vs-post/…
4 Stimmen
Du weißt... mir ist klar, dass die Spezifikation PUT als 'aktualisieren' bezeichnet, aber ich denke, jeder wäre viel weniger verwirrt, wenn wir es 'ersetzen' nennen würden, das ist schließlich, was es tut.
3 Stimmen
Im Prinzip funktioniert POST gut für das Erstellen von Ressourcen. Die URL der neu erstellten Ressource sollte im Location-Antwortheader zurückgegeben werden. PUT sollte verwendet werden, um eine Ressource vollständig zu aktualisieren. Bitte verstehen Sie, dass dies die bewährten Methoden beim Entwerfen einer RESTful-API sind. Die HTTP-Spezifikation als solche schränkt die Verwendung von PUT/POST für das Erstellen/Aktualisieren von Ressourcen nicht ein paar Einschränkungen ein. Werfen Sie einen Blick auf techoctave.com/c7/posts/71-twitter-rest-api-dissected, das die bewährten Methoden zusammenfasst.
3 Stimmen
Idempotenz
ist der Schlüssel. Lesen Sie PUT oder POST: Die REST-Geschichte von John Calcote. Wenn Ihre Methode idempotent ist, verwenden Sie PUT. Andernfalls verwenden Sie POST.2 Stimmen
Ich verstehe den vorherrschenden Konsens dazu nicht. Die Zitierung des OP für PUT beginnt mit "Die PUT-Methode fordert, dass die enthaltene Entität gespeichert wird....". Das sagt mir "Erstellung". Wenn wir über "etwas hinzufügen" sprechen, sprechen wir von einem Ort, an dem es zuvor nicht war. Du "fuegst" etwas nicht hinzu, um es zu ändern. Wenn Sie ein Dokument ändern, fügen Sie nicht ein neues hinzu. Die Verwendung des HTTP-Verbs PUT um "aktualisieren" zu bedeuten, ist eine schlechte semantische Anpassung.
1 Stimmen
PUT begann als Möglichkeit für frühe Microsoft HTML-Designwerkzeuge, Inhalte direkt auf einen Server zu veröffentlichen. Die Tatsache, dass es auch zum Aktualisieren (im Großen und Ganzen) verwendet wurde, war auf das Fehlen einer anderen Aktualisierungsmethode zurückzuführen. Auch wenn es sich um ein Großhandels-Update handelte, war es wirklich eine Erstellung, nur eine, die idempotent war. Ein "Update" impliziert, dass ein Aspekt des vorherigen Zustands beibehalten wurde.
1 Stimmen
Echtes Szenario in der Elasticsearch-Dokumentation: elastic.co/guide/en/elasticsearch/reference/current/…. Werfen Sie einen Blick auf den Unterschied zwischen allen PUT-Anfragen und dem letzten POST-Anfragebeispiel.
0 Stimmen
Das
JavaBrains
erklärt es sehr klar. Schau dir youtube.com/watch?v=rhTkRK53XdQ an.0 Stimmen
Die Unterschied zwischen den Methoden POST vs PUT sollte im definierten Kontext beschrieben werden. Zum Beispiel hier, die Frage dreht sich um REST und dreht sich tatsächlich um Konsistenz und eine einheitliche Schnittstelle. Solange du die Konsistenz im API-Design respektierst, bist du auf dem richtigen Weg.
0 Stimmen
Beachten Sie, dass wenn Sie möchten, dass eine Webanwendung auch funktioniert, wenn JavaScript deaktiviert ist, sollten Sie POST verwenden: stackoverflow.com/questions/630453/put-vs-post-in-rest/…
0 Stimmen
Die zitierte Aussage des OP über POST ist nicht mehr gültig. "Die tatsächliche Funktion, die von der POST-Methode ausgeführt wird, wird vom Server bestimmt und hängt normalerweise vom effektiven Anfrageresource-Identifikator (URI) ab. Die Aktion, die von der POST-Methode ausgeführt wird, führt möglicherweise nicht zu einer Ressource, die mit einem URI identifiziert werden kann." über tools.ietf.org/html/…
0 Stimmen
Die Idempotenz ist wichtig. Aber um idempotent zu sein, muss man einen eindeutigen Schlüssel (oder eine Reihe von Schlüsseln) haben. Wenn der eindeutige Schlüssel in einem POST-Aufruf zweimal angegeben wird, sollte der zweite einen Fehler erzeugen. In einem PUT-Aufruf sollte er das Ressource erstellen/aktualisieren/ersetzen. Es ist möglich, einen POST-Aufruf ohne einen eindeutigen Schlüssel durchzuführen (es wird einfach jedes Mal eine neue Ressource erstellt). Es ist jedoch nicht möglich, einen PUT-Aufruf ohne Schlüssel durchzuführen.
0 Stimmen
All diese Diskussionen über die Idempotenz von PUT und das Fehlen dieser Eigenschaft bei POST ignorieren das eigentliche Problem. Der Browser wird bei beiden, sogar bei POST, erneut versuchen, wenn die Verbindung vom Server geschlossen wird. Daher müssen Sie Ihre API so entwickeln, dass sie unabhhängig davon idempotent ist, damit Sie sich nicht beschweren können, wenn es passiert! :) Die Wahl der Methode ist fast belanglos. stackoverflow.com/questions/15155014/… w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.4