6336 Stimmen

Was ist der Unterschied zwischen POST und PUT in HTTP?

Hintergrundinformationenanalyse:

Gemäß RFC 2616, § 9.5 wird POST verwendet, um eine Ressource zu erstellen:

Die POST-Methode wird verwendet, um zu fordern, dass der Ursprungsserver die im Request eingebettete Entität als neue untergeordnete Ressource der im Request-Zeilen-URI identifizierten Ressource akzeptiert.

Gemäß RFC 2616, § 9.6 wird PUT verwendet, um eine Ressource zu erstellen oder zu ersetzen:

Die PUT-Methode fordert, dass die eingebettete Entität unter dem bereitgestellten Request-URI gespeichert wird. Wenn der Request-URI auf eine bereits vorhandene Ressource verweist, sollte die eingebettete Entität als modifizierte Version derjenigen angesehen werden, die auf dem Ursprungsserver liegt. Wenn der Request-URI nicht auf eine vorhandene Ressource zeigt und dieser URI als neue Ressource vom anfordernden User-Agent definiert werden kann, kann der Ursprungsserver die Ressource mit diesem URI erstellen.

Meine Frage:

Also, welche HTTP-Methode sollte verwendet werden, um eine Ressource zu erstellen? Oder sollten beide unterstützt werden?

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.

193voto

ThaDon Punkte 7504

Ich würde gerne meinen "pragmatischen" Rat hinzufügen. Verwenden Sie PUT, wenn Sie die "Id" kennen, mit der das Objekt, das Sie speichern, abgerufen werden kann. Wenn Sie beispielsweise eine vom Datenbank generierte Id benötigen, um zukünftige Suchvorgänge oder Aktualisierungen durchzuführen, funktioniert PUT nicht besonders gut.

Also: Um einen vorhandenen Benutzer oder einen Benutzer zu speichern, bei dem der Client die Id generiert und überprüft wurde, dass die Id eindeutig ist:

PUT /user/12345 HTTP/1.1  <-- erstelle den Benutzer mit der Id 12345
Host: mydomain.example

GET /user/12345 HTTP/1.1  <-- gib diesen Benutzer zurück
Host: mydomain.example

Andernfalls verwenden Sie POST, um das Objekt zuerst zu erstellen, und PUT, um das Objekt zu aktualisieren:

POST /user HTTP/1.1   <--- Benutzer erstellen, Server gibt 12345 zurück
Host: mydomain.example

PUT /user/12345 HTTP/1.1  <--- Benutzer aktualisieren
Host: mydomain.example

20 Stimmen

Eigentlich sollte es POST /users sein. (Beachten Sie, dass /users plural ist.) Dies hat zur Folge, dass ein neuer Benutzer erstellt und als untergeordnete Ressource der /users Sammlung hinzugefügt wird.

6 Stimmen

@DavidRR um fair zu sein, wie man mit Gruppen umgeht, ist eine ganz andere Debatte. GET /benutzer macht Sinn, es liest sich so, wie man es möchte, aber ich wäre auch mit GET /benutzer/ oder POST /benutzer (mit Payload für diesen neuen Benutzer) einverstanden, weil es sich richtig liest 'hol mir Benutzer 5' ist seltsam, aber 'hol mir Benutzer 5' ist natürlicher. Ich würde wahrscheinlich trotzdem auf der Seite der Pluralbildung bleiben :)

4 Stimmen

@thecoshman Du kannst es lesen wie 'Hole mir die ID 5 von Benutzern' ;)

173voto

Premraj Punkte 65511

Beide werden für die Datenübertragung zwischen Client und Server verwendet, aber es gibt subtile Unterschiede zwischen ihnen, die sind:

PUT

POST

Ersetzen einer vorhandenen Ressource oder Erstellen, wenn die Ressource nicht vorhanden ist. www.example.com/com/customer/{customerId} www.example.com/com/customer/123/order/{orderId} Der Identifier wird vom Client gewählt.

Erstellen neuer Ressourcen und untergeordneter Ressourcen, z.B. eine Datei ist untergeordnet einem Verzeichnis, das sie enthält, oder eine Zeile ist untergeordnet einer Datenbanktabelle. www.example.com/com/customer/ www.example.com/com/customer/123/order/ Der Identifier wird vom Server zurückgegeben.

Idempotent, d.h. Wenn Sie eine Ressource zweimal PUT, hat dies keine Auswirkung. Beispiel: Tun Sie es so oft Sie wollen, das Ergebnis wird dasselbe sein. x=1;

POST ist weder sicher noch idempotent. Beispiel: x++;

Funktioniert spezifisch

Funktioniert abstraktiv

Wenn Sie eine Ressource mit PUT erstellen oder aktualisieren und dann denselben Aufruf erneut tätigen, ist die Ressource immer noch vorhanden und hat den gleichen Zustand wie beim ersten Aufruf.

Zwei identische POST-Anfragen werden höchstwahrscheinlich in zwei Ressourcen resultieren, die die gleichen Informationen enthalten.

Analogie:

  • PUT, also nehmen und setzen wo es war.
  • POST wie das Senden von Post in der Postfiliale.

Bildbeschreibung eingeben

Analgie zu sozialen Medien/Netzwerken:

  • Posten in sozialen Medien: Wenn wir eine Nachricht posten, wird ein neuer Beitrag erstellt.
  • Put (d.h. bearbeiten) für die Nachricht, die wir bereits gepostet haben.

24 Stimmen

@MobileMon Nein, REST-Methoden sind nicht CRUD.

4 Stimmen

Ich würde PUT für UPSERTS sagen.

1 Stimmen

@MobileMon: POST, wenn Sie eine neue Ressource erstellen und den endgültigen Endpunkt nicht kennen. Verwenden Sie PUT für andere Fälle.

156voto

Tim Sullivan Punkte 16549

Verwenden Sie POST zum Erstellen und PUT zum Aktualisieren. So macht es jedenfalls Ruby on Rails.

PUT    /artikel/1      #=> aktualisieren
POST   /artikel        #=> erstellen

4 Stimmen

POST /items fügt ein neues Element zu einem bereits definierten Ressourcen ('item') hinzu. Es erstellt nicht, wie die Antwort sagt, "eine Gruppe". Ich verstehe nicht, warum das 12 Stimmen hat.

0 Stimmen

Standardmäßig unterstützt Rails das Erstellen einer Gruppe über REST nicht. Um eine Gruppe zu erstellen, was bedeutet, eine Ressource zu erstellen, muss dies über den Quellcode erfolgen.

0 Stimmen

Es hat 12 Stimmen, weil es vor der Änderung gemacht wurde, die die Gruppenoption hinzugefügt hat. Ich habe die Änderung rückgängig gemacht.

75voto

Jörg W Mittag Punkte 349574

REST ist ein sehr hochrangiges Konzept. Tatsächlich erwähnt es nicht einmal HTTP!

Wenn Sie Zweifel haben, wie Sie REST in HTTP implementieren können, können Sie immer einen Blick auf die Atom-Publikationsprotokoll (AtomPub) Spezifikation werfen. AtomPub ist ein Standard zur Erstellung von RESTful-Webservices mit HTTP, der von vielen HTTP- und REST-Experten entwickelt wurde, mit einigen Beiträgen von Roy Fielding, dem Erfinder von REST und (Mit-)Erfinder von HTTP selbst.

Tatsächlich könnten Sie AtomPub sogar direkt verwenden. Obwohl es aus der Blog-Community stammt, ist es keineswegs auf Blogs beschränkt: Es ist ein generisches Protokoll zum RESTful-Interagieren mit beliebigen (verschachtelten) Sammlungen von beliebigen Ressourcen über HTTP. Wenn Sie Ihre Anwendung als eine verschachtelte Sammlung von Ressourcen darstellen können, können Sie einfach AtomPub verwenden und sich keine Gedanken darüber machen, ob Sie PUT oder POST verwenden, welche HTTP-Statuscodes Sie zurückgeben sollen und all diese Details.

Dies sagt AtomPub zur Ressourcenerstellung (Abschnitt 9.2):

Um Mitglieder zu einer Sammlung hinzuzufügen, senden Clients POST-Anfragen an die URI der Sammlung.

9 Stimmen

Es ist nichts falsch daran, PUT zu erlauben, Ressourcen zu erstellen. Sei dir nur bewusst, dass dies bedeutet, dass der Client die URL bereitstellt.

6 Stimmen

Es ist sehr problematisch, PUT zu erlauben, Ressourcen zu erstellen: Der Client gibt die URL vor. Das ist die Aufgabe des Servers!

0 Stimmen

@Joshcodes Es ist nicht immer der Fall, dass es die Aufgabe des Servers ist, Client-IDs zu erstellen. Ich habe zunehmend Designs gesehen, bei denen Clients eine Art UUID als Ressourcen-ID generieren können. Dieses Design eignet sich besonders zur Steigerung des Maßstabs.

72voto

Joshcodes Punkte 7993

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:

  1. Der Client sendet eine neue Ressource an den Server.
  2. Der Server verarbeitet die Anfrage und sendet eine Antwort zurück.
  3. Der Client erhält die Antwort nie.
  4. Der Server ist sich nicht bewusst, dass der Client die Antwort nicht erhalten hat.
  5. Der Client hat keine URL für die Ressource (deshalb ist PUT keine Option) und wiederholt den POST.
  6. 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.

0 Stimmen

Wäre eine 409-Konfliktantwort der geeignete Code für etwas wie den Versuch, ein neues Konto mit einem bereits vorhandenen Benutzernamen zu erstellen? Ich habe 409 bisher speziell für Versionskonflikte verwendet, aber nachdem ich Ihre Antwort gelesen habe, frage ich mich, ob es nicht für alle "doppelten" Anfragen verwendet werden sollte.

0 Stimmen

@EricB. Ja, in der Situation, die Sie beschreiben, "aufgrund eines Konflikts mit dem aktuellen Zustand der Ressource" schlägt die Operation fehl. Es ist auch vernünftig zu erwarten, dass der Benutzer den Konflikt lösen kann und der Nachrichtentext nur den Benutzer darüber informieren muss, dass der Benutzername bereits vorhanden ist.

0 Stimmen

@Joshcodes, kannst du mehr über den Konfliktlösungsprozess sagen? In diesem Fall, wenn der Benutzername bereits existiert, soll der Kunde den Endbenutzer auffordern, einen anderen Benutzernamen einzugeben? Was ist, wenn der Kunde tatsächlich versucht, mit POST den Benutzernamen zu ändern? Sollten PUT-Anfragen immer noch verwendet werden, um Parameter zu aktualisieren, während POST verwendet wird, um Objekte zu erstellen, sei es einzeln oder mehrere? Vielen Dank.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X