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.

22voto

bbsimonbb Punkte 23637

Leser, die neu in diesem Thema sind, werden von der endlosen Diskussion darüber, was Sie tun sollten, und dem relativen Mangel an Erfahrungen beeindruckt sein. Die Tatsache, dass REST "bevorzugt" wird gegenüber SOAP, ist, nehme ich an, ein Lernen auf hoher Ebene aus Erfahrungen, aber Gut, wir müssen von dort aus vorangekommen sein, oder? Es ist 2016. Roys Dissertation war im Jahr 2000. Was haben wir entwickelt? War es lustig? War es einfach zu integrieren? Zu unterstützen? Wird es den Anstieg von Smartphones und instabilen mobilen Verbindungen bewältigen?

Nach ME sind die realen Netzwerke unzuverlässig. Anfragen laufen ab. Verbindungen werden zurückgesetzt. Netzwerke fallen stunden- oder tagelang aus. Züge fahren in Tunnel mit mobilen Benutzern an Bord. Für eine beliebige Anfrage (wie gelegentlich in all diesen Diskussionen anerkannt) kann die Anfrage auf ihrem Weg ins Wasser fallen oder die Antwort kann auf ihrem Rückweg ins Wasser fallen. Unter diesen Bedingungen erscheinen mir das direkte Ausgeben von PUT-, POST- und DELETE-Anfragen gegen substantielle Ressourcen immer ein wenig brutal und naiv.

HTTP tut nichts, um die zuverlässige Beendigung der Anfrage-Antwort zu gewährleisten, und das ist in Ordnung, denn das ist eigentlich die Aufgabe von netzwerkbezogenen Anwendungen. Bei der Entwicklung einer solchen Anwendung können Sie sich durch Reifen springen, um PUT anstelle von POST zu verwenden, dann durch weitere Reifen, um auf dem Server eine bestimmte Art von Fehler zu geben, wenn Sie doppelte Anfragen feststellen. Zurück beim Client müssen Sie dann durch Reifen springen, um diese Fehler zu interpretieren, neu abzurufen, neu zu validieren und erneut zu senden.

Oder Sie können dies tun: Betrachten Sie Ihre unsicheren Anfragen als ephemere Einzelbenutzer-Ressourcen (nennen wir sie Aktionen). Clients fordern eine neue "Aktion" auf einer substantiellen Ressource mit einem leeren POST auf die Ressource an. POST wird nur hierfür verwendet. Sobald der Client im Besitz des URIs der frisch erstellten Aktion ist, PUT der Client die unsichere Anfrage auf den Aktions-URI, nicht auf die Zielressource. Das Bearbeiten der Aktion und Aktualisieren der "echten" Ressource ist die eigentliche Aufgabe Ihrer API und hier von dem unzuverlässigen Netzwerk entkoppelt.

Der Server erledigt das Geschäft, liefert die Antwort zurück und speichert sie am vereinbarten Aktions-URI ab. Wenn etwas schiefgeht, wiederholt der Client die Anfrage (natürliches Verhalten!), und wenn der Server sie bereits gesehen hat, wiederholt er die gespeicherte Antwort und tut nichts weiteres.

Sie werden schnell die Ähnlichkeit mit Versprechen erkennen: Wir erstellen und geben den Platzhalter für das Ergebnis zurück, bevor wir irgendetwas tun. Wie bei einem Versprechen kann eine Aktion einmal erfolgreich oder erfolglos sein, aber ihr Ergebnis kann wiederholt abgerufen werden.

Am besten geben wir den sendenden und empfangenden Anwendungen die Möglichkeit, die eindeutig identifizierte Aktion mit der Einzigartigkeit in ihren jeweiligen Umgebungen zu verknüpfen. Und wir können anfangen, verantwortungsvolles Verhalten von Clients zu verlangen und durchzusetzen: Wiederholen Sie Ihre Anfragen so oft Sie möchten, aber generieren Sie keine neue Aktion, bis Sie im Besitz eines definitiven Ergebnisses von der vorhandenen sind.

Auf diese Weise verschwinden zahlreiche knifflige Probleme. Wiederholte Einfügeanforderungen erzeugen keine Duplikate, und wir erstellen die echte Ressource nicht, bis wir im Besitz der Daten sind (Datenbankspalten können nicht-nulle bleiben). Wiederholte Update-Anforderungen führen nicht zu inkonsistenten Zuständen und überschreiben keine nachfolgenden Änderungen. Clients können die ursprünglichen Bestätigungen (zum Beispiel bei einem Absturz des Clients, wenn die Antwort verloren gegangen ist usw.) (wieder) abrufen und nahtlos verarbeiten.

Folgende Lösch-Anfragen können die ursprüngliche Bestätigung sehen und verarbeiten, ohne einen 404-Fehler zu erzeugen. Wenn die Dinge länger als erwartet dauern, können wir vorläufig antworten, und wir haben einen Ort, an dem der Client für das endgültige Ergebnis nachsehen kann. Das Schönste an diesem Muster ist seine Kung-Fu (Panda)-Eigenschaft. Wir nehmen eine Schwäche, die Neigung von Clients, eine Anfrage zu wiederholen, wenn sie die Antwort nicht verstehen, und machen sie zu einer Stärke :-)

Bevor Sie mir sagen, dass dies nicht RESTful ist, überlegen Sie bitte die zahlreichen Möglichkeiten, in denen REST-Prinzipien respektiert werden. Clients konstruieren keine URLs. Die API bleibt auffindbar, wenn auch mit einer kleinen Änderung der Semantik. HTTP-Verben werden angemessen verwendet. Wenn Sie denken, dass dies eine große Änderung in seiner Umsetzung ist, kann ich Ihnen aus Erfahrung sagen, dass es nicht so ist.

Wenn Sie denken, dass Sie enorme Datenmengen speichern müssen, lassen Sie uns über Volumina sprechen: Eine typische Update-Bestätigung ist nur ein Bruchteil eines Kilobyte. HTTP gibt Ihnen derzeit eine Minute oder zwei Zeit, um endgültig zu antworten. Selbst wenn Sie Aktionen nur für eine Woche speichern, haben Clients ausreichend Gelegenheit, aufzuholen. Wenn Sie sehr hohe Volumina haben, möchten Sie möglicherweise ein dediziertes acid-konformes Schlüssel-Wert-Speicher oder eine In-Memory-Lösung.

2 Stimmen

Wird das Speichern der Antwort nicht wie das Aufrechterhalten einer Sitzung sein? Was zu (horizontalen) Skalierungsproblemen führen würde.

20voto

Burhan Punkte 233

Es scheint immer wieder Verwirrung darüber zu geben, wann man die HTTP-POST- und die HTTP-PUT-Methode für REST-Dienste verwenden sollte. Die meisten Entwickler werden versuchen, CRUD-Operationen direkt mit HTTP-Methoden zu verknüpfen. Ich werde argumentieren, dass dies nicht korrekt ist und man die CRUD-Konzepte nicht einfach mit den HTTP-Methoden in Verbindung bringen kann. Das heißt:

Erstellen => HTTP PUT
Abrufen => HTTP GET
Aktualisieren => HTTP POST
Löschen => HTTP DELETE

Es stimmt, dass das A(brufen) und D(elete) der CRUD-Operationen direkt den HTTP-Methoden GET und DELETE zugeordnet werden können. Die Verwirrung liegt jedoch in den C(reieren) und U(pdate) Operationen. In einigen Fällen kann man PUT für ein Erstellen verwenden, während in anderen Fällen ein POST erforderlich sein wird. Die Unklarheit liegt in der Definition einer HTTP-PUT-Methode im Vergleich zu einer HTTP-POST-Methode.

Nach den Spezifikationen von HTTP 1.1 müssen die Methoden GET, HEAD, DELETE und PUT idempotent sein, und die POST-Methode ist nicht idempotent. Das heißt, eine Operation ist idempotent, wenn sie einmal oder mehrmals auf eine Ressource angewendet werden kann und immer den gleichen Zustand dieser Ressource zurückgibt. Während eine nicht-idempotente Operation einen modifizierten Zustand der Ressource von einer Anfrage zur nächsten zurückgeben kann. In einer nicht-idempotenten Operation besteht also keine Garantie, dass man den gleichen Zustand einer Ressource erhält.

Basierend auf der obigen Definition von Idempotenz ist mein Standpunkt zur Verwendung der HTTP PUT-Methode versus der Verwendung der HTTP POST-Methode für REST-Dienste:

Verwende die HTTP PUT-Methode, wenn:
Der Client alle Aspekte der Ressource einschließlich des eindeutigen Bezeichners enthält, um die Ressource eindeutig zu identifizieren. Beispiel: Erstellen eines neuen Mitarbeiters.
Der Client alle Informationen für eine Ressource bereitstellt, um diese Ressource ändern zu können. Dies impliziert, dass die Serverseite keinen Aspekt der Ressource aktualisiert (wie ein Aktualisierungsdatum).

In beiden Fällen können diese Operationen mehrmals mit denselben Ergebnissen ausgeführt werden. Das bedeutet, dass sich die Ressource durch mehrmaliges Ausführen des Vorgangs nicht ändert. Daher eine echte idempotente Operation. Verwende die HTTP POST-Methode, wenn:

Der Server einige Informationen über die neu erstellte Ressource bereitstellen wird. Zum Beispiel ein Protokollsystem. Ein neuer Eintrag im Protokoll hat höchstwahrscheinlich ein Nummerierungsschema, das auf der Serverseite festgelegt ist. Beim Erstellen eines neuen Protokolleintrags wird die neue Sequenznummer vom Server bestimmt und nicht vom Client.
Bei einer Änderung einer Ressource wird der Server Informationen wie einen Ressourcenstatus oder ein Aktualisierungsdatum bereitstellen. Auch in diesem Fall wurden nicht alle Informationen vom Client bereitgestellt und die Ressource wird sich von einer Änderungsanfrage zur nächsten ändern. Daher eine nicht-idempotente Operation.

Schlussfolgerung

Korreliere und beziehe CRUD-Operationen nicht direkt auf HTTP-Methods für REST-Dienste. Die Verwendung einer HTTP PUT-Methode gegenüber einer HTTP POST-Methode sollte auf dem idempotenten Aspekt dieser Operation basieren. Das heißt, wenn die Operation idempotent ist, dann verwende die HTTP PUT-Methode. Wenn die Operation nicht idempotent ist, verwende die HTTP POST-Methode.

4 Stimmen

Aktualisierung => HTTP POST: POST ist nicht zum Aktualisieren geeignet

0 Stimmen

@premraj Du hast die Annahme gemacht, die Burhan dir nicht macht; nämlich, du vermischst CRUD, REST und HTTP. Wenn du RFC 7231 liest, wo diese Dinge definiert sind, wirst du feststellen, dass im HTTP-Protokoll die Definition von POST sicherlich Aktualisierungen erlaubt. Es sind nur die Einschränkungen von REST, die etwas anderes sagen.

18voto

inf3rno Punkte 22107

Der Ursprungsserver kann die Ressource mit diesem URI erstellen

Sie verwenden also POST und wahrscheinlich, aber nicht unbedingt PUT zur Ressourcenerstellung. Sie müssen nicht beide unterstützen. Für mich ist POST vollkommen ausreichend. Es ist also eine Designentscheidung.

Wie Ihr Zitat erwähnt hat, verwenden Sie PUT zur Erstellung, wenn keine Ressource einem IRI zugewiesen ist und Sie trotzdem eine Ressource erstellen möchten. Zum Beispiel ersetzt PUT /Benutzer/123/Passwort normalerweise das alte Passwort durch ein neues, aber Sie können es verwenden, um ein Passwort zu erstellen, falls es noch nicht vorhanden ist (zum Beispiel bei frisch registrierten Benutzern oder bei wiederhergestellten gesperrten Benutzern).

1 Stimmen

Ich glaube, du hast es geschafft, ein gutes Beispiel dafür zu geben, wie PUT verwendet werden kann, gut gemacht.

17voto

Gerard ONeill Punkte 3528

Ich werde mit dem folgenden landen:

PUT bezieht sich auf eine Ressource, die durch die URI identifiziert ist. In diesem Fall aktualisieren Sie es. Es ist Teil der drei Verben, die sich auf Ressourcen beziehen -- Löschen und Abrufen sind die anderen beiden.

POST ist im Grunde genommen eine freie Form von Nachricht, deren Bedeutung 'out of band' definiert ist. Wenn die Nachricht als Hinzufügen einer Ressource zu einem Verzeichnis interpretiert werden kann, wäre dies in Ordnung, aber im Grunde genommen müssen Sie die Nachricht verstehen, die Sie senden (posten), um zu wissen, was mit der Ressource passieren wird.


Weil PUT und GET und DELETE sich auf eine Ressource beziehen, sind sie auch von definition her idempotent.

POST kann die anderen drei Funktionen ausführen, aber dann gehen die Semantik des Requests für Zwischenhändler wie Caches und Proxies verloren. Das gilt auch für die Bereitstellung von Sicherheit für die Ressource, da die URI eines Posts nicht unbedingt die Ressource angibt, auf die er angewendet wird (es könnte aber auch).

Ein PUT muss keine Erstellung sein; der Dienst könnte einen Fehler ausgeben, wenn die Ressource noch nicht erstellt wurde, aber sie andererseits aktualisieren. Oder umgekehrt - es könnte die Ressource erstellen, aber keine Updates zulassen. Das Einzige, was bei PUT erforderlich ist, ist, dass es auf eine spezifische Ressource verweist, und sein Payload ist die Repräsentation dieser Ressource. Ein erfolgreicher PUT bedeutet (unter Vorbehalt von Störungen), dass ein GET die gleiche Ressource abrufen würde.


Bearbeiten: Noch etwas - ein PUT kann erstellen, aber wenn er dies tut, muss die ID eine natürliche ID sein - AKA eine E-Mail-Adresse. Auf diese Weise ist der zweite PUT eine Aktualisierung des ersten, wenn zweimal PUT ausgeführt wird. Dies macht es idempotent.

Wenn die ID generiert wird (zum Beispiel eine neue Mitarbeiter-ID), würde der zweite PUT mit derselben URL einen neuen Datensatz erstellen, was gegen die idempotente Regel verstößt. In diesem Fall wäre das Verb POST, und die Nachricht (nicht die Ressource) würde dazu dienen, eine Ressource mit den in dieser Nachricht definierten Werten zu erstellen.

14voto

Adam Griffiths Punkte 1556

Hier ist eine einfache Regel:

PUT sollte verwendet werden, um eine Ressource unter einer bestimmten URL zu aktualisieren oder zu erstellen.

POST sollte verwendet werden, um eine Ressource zu aktualisieren oder zu erstellen, die sich an einer anderen ("untergeordneten") URL befindet oder über HTTP nicht lokalisierbar ist.

1 Stimmen

PUT ist nicht für ein Update, sondern für einen Austausch gedacht. Beachten Sie, dass Sie beim Erstellen etwas durch etwas anderes ersetzen. POST ist absolut nicht für ein Update in irgendeiner Form gedacht.

3 Stimmen

Ist das im http spezifiziert? Oder basierst du deinen Kommentar auf etwas anderem?

0 Stimmen

Es ist einfach logisch, wie man etwas aktualisiert, wenn man nicht weiß, was man aktualisiert. POST ist zum Erstellen einer neuen Ressource.

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