PUT vs. POST in REST

5373

Gemäß der HTTP / 1.1-Spezifikation:

Das POSTVerfahren ist nicht auf Anforderung verwendet , dass der Ursprungsserver die Entität in der Anforderung als eine neue untergeordnete der Ressource durch die identifizierten umschlossenen nehmen Request-URIin derRequest-Line

Mit anderen Worten, POSTwird zum Erstellen verwendet .

Die PUTMethode fordert an, dass die eingeschlossene Entität unter der angegebenen gespeichert wird Request-URI. Wenn sich das Request-URIauf eine bereits vorhandene Ressource bezieht, MUSS die eingeschlossene Entität als modifizierte Version der auf dem Ursprungsserver befindlichen Entität betrachtet werden. Wenn der Request-URInicht auf eine vorhandene Ressource verweist und dieser URI vom anfordernden Benutzeragenten als neue Ressource definiert werden kann, kann der Ursprungsserver die Ressource mit diesem URI erstellen. "

Das heißt, PUTwird zum Erstellen oder Ersetzen verwendet .

Welches sollte also verwendet werden, um eine Ressource zu erstellen? Oder muss man beides unterstützen?

Alex
quelle
56
Es kann hilfreich sein, die Definitionen in HTTPbis zu verwenden - Roy hat eine Menge Arbeit in die Klärung dieser Definitionen gesteckt. Siehe: tools.ietf.org/html/…
Mark Nottingham
16
Um @ MarkNottinghams Kommentar zur neuesten Revision zu bringen, hier POST und PUT , wie auf HTTPbis definiert.
Marius Butuc
37
Es scheint mir, dass diese Debatte aus der gängigen Praxis der Vereinfachung von REST durch die Beschreibung der HTTP-Methoden in Bezug auf CRUD-Operationen entstanden ist.
Stuporman
5
Leider sind die ersten Antworten bezüglich POST falsch. Überprüfen Sie meine Antwort für eine bessere Erklärung der Unterschiede: stackoverflow.com/a/18243587/2458234
7hi4g0
23
PUT und POST sind beide unsichere Methoden. PUT ist jedoch idempotent, POST nicht. - Weitere Informationen finden Sie unter
Dinesh Saini

Antworten:

4239

Insgesamt:

Sowohl PUT als auch POST können zum Erstellen verwendet werden.

Sie müssen fragen: "Wozu führen Sie die Aktion aus?" um zu unterscheiden, was Sie verwenden sollten. Angenommen, Sie entwerfen eine API zum Stellen von Fragen. Wenn Sie POST verwenden möchten, tun Sie dies mit einer Liste von Fragen. Wenn Sie PUT verwenden möchten, würden Sie dies für eine bestimmte Frage tun.

Großartig, beide können verwendet werden, also welches sollte ich in meinem RESTful-Design verwenden:

Sie müssen nicht sowohl PUT als auch POST unterstützen.

Was verwendet wird, bleibt Ihnen überlassen. Denken Sie jedoch daran, das richtige zu verwenden, je nachdem, auf welches Objekt Sie in der Anforderung verweisen.

Einige Überlegungen:

  • Benennen Sie Ihre URL-Objekte, die Sie explizit erstellen, oder lassen Sie den Server entscheiden? Wenn Sie sie benennen, verwenden Sie PUT. Wenn Sie den Server entscheiden lassen, verwenden Sie POST.
  • PUT ist idempotent. Wenn Sie also ein Objekt zweimal PUTEN, hat dies keine Auswirkung. Dies ist eine schöne Eigenschaft, daher würde ich PUT verwenden, wenn dies möglich ist.
  • Sie können eine Ressource mit PUT mit derselben Objekt-URL aktualisieren oder erstellen
  • Mit POST können zwei Anfragen gleichzeitig eingehen, die Änderungen an einer URL vornehmen, und sie können verschiedene Teile des Objekts aktualisieren.

Ein Beispiel:

Ich habe Folgendes als Teil einer anderen Antwort auf SO zu diesem Thema geschrieben :

POST:

Wird zum Ändern und Aktualisieren einer Ressource verwendet

POST /questions/<existing_question> HTTP/1.1
Host: www.example.com/

Beachten Sie, dass Folgendes ein Fehler ist:

POST /questions/<new_question> HTTP/1.1
Host: www.example.com/

Wenn die URL noch nicht erstellt wurde, sollten Sie POST nicht verwenden, um sie zu erstellen, während Sie den Namen angeben. Dies sollte zu einem Fehler "Ressource nicht gefunden" führen, da dieser <new_question>noch nicht vorhanden ist. Sie sollten die <new_question> Ressource zuerst auf den Server stellen.

Sie können jedoch Folgendes tun, um mithilfe von POST Ressourcen zu erstellen:

POST /questions HTTP/1.1
Host: www.example.com/

Beachten Sie, dass in diesem Fall der Ressourcenname nicht angegeben wird und der URL-Pfad für neue Objekte an Sie zurückgegeben wird.

STELLEN:

Wird verwendet, um eine Ressource zu erstellen oder zu überschreiben. Während Sie die Ressourcen neue URL angeben.

Für eine neue Ressource:

PUT /questions/<new_question> HTTP/1.1
Host: www.example.com/

So überschreiben Sie eine vorhandene Ressource:

PUT /questions/<existing_question> HTTP/1.1
Host: www.example.com/

Zusätzlich und etwas präziser, RFC 7231 Abschnitt 4.3.4 PUT- Zustände (Hervorhebung hinzugefügt),

4.3.4. STELLEN

Die PUT-Methode fordert an, dass der Status der Zielressource createdoder replacedder Status ist, der durch die in der Nutzlast der Anforderungsnachricht enthaltene Darstellung definiert ist.

Brian R. Bondy
quelle
1026
Ich denke, man kann die Tatsache, dass PUT idempotent ist, nicht genug betonen: Wenn das Netzwerk verpfuscht ist und der Client nicht sicher ist, ob seine Anfrage es geschafft hat, kann er es nur ein zweites (oder 100.) Mal senden, und es wird von der garantiert HTTP-Spezifikation, dass dies genau den gleichen Effekt hat wie einmaliges Senden.
Jörg W Mittag
77
@ Jörg W Mittag: Nicht nötig. Das zweite Mal könnte 409 Conflict oder etwas zurückgeben, wenn die Anforderung in der Zwischenzeit geändert wurde (von einem anderen Benutzer oder der ersten Anforderung selbst, die durchgekommen ist).
Mitar
632
Wenn ich mich nicht irre, sollten wir betonen, dass PUT als idempotent definiert ist. Sie müssen Ihren Server immer noch so schreiben, dass sich PUT korrekt verhält, ja? Vielleicht ist es besser zu sagen, dass "PUT bewirkt, dass der Transport Idempotenz annimmt, was das Verhalten des Transports beeinflussen kann, z. B. Caching."
Ian Ni-Lewis
150
@ JörgWMittag Idempotenz-Schlagwort? Wie wäre es mit "Senden und senden und senden Sie meinen Freund, es macht am Ende keinen Unterschied."
James Beninger
39
Betrachtet sie als: PUT = Einfügen oder Aktualisieren; POST = einfügen. Wenn Sie also zwei PUTs erstellen - Sie erhalten den einen neuen Datensatz, wenn Sie zwei POSTs ausführen - erhalten Sie zwei neue Datensätze.
Eugen Konkov
2218

Im Internet finden Sie Aussagen, die besagen

Beides ist nicht ganz richtig.


Besser ist es, zwischen PUT und POST zu wählen, basierend auf der Idempotenz der Aktion.

PUT bedeutet, eine Ressource zu platzieren und alles, was unter der angegebenen URL verfügbar ist, vollständig durch eine andere zu ersetzen. Per Definition ist ein PUT idempotent. Tun Sie es so oft Sie möchten, und das Ergebnis ist das gleiche. x=5ist idempotent. Sie können eine Ressource PUTEN, unabhängig davon, ob sie bereits vorhanden ist oder nicht (z. B. zum Erstellen oder Aktualisieren)!

POST aktualisiert eine Ressource, fügt eine untergeordnete Ressource hinzu oder bewirkt eine Änderung. Ein POST ist nicht idempotent, so wie er x++nicht idempotent ist.


Mit diesem Argument dient PUT zum Erstellen, wenn Sie die URL des zu erstellenden Objekts kennen. POST kann zum Erstellen verwendet werden, wenn Sie die URL der "Fabrik" oder des Managers für die Kategorie der Dinge kennen, die Sie erstellen möchten.

damit:

POST /expense-report

oder:

PUT  /expense-report/10929
Cheeso
quelle
72
Ich stimme zu, wenn es um Idempotenz geht, sollte sie alle anderen Bedenken übertreffen, da ein Fehler falsch viele, viele unerwartete Fehler verursachen kann.
Josh
16
Wenn POST eine Ressource aktualisieren kann, wie ist das nicht idempotent? Wenn ich das Alter eines Schülers mit PUT ändere und dies zehnmal mache, ist das Alter des Schülers das gleiche, wenn ich es einmal getan habe.
Jack Ukleja
28
@Schneider, in diesem Fall unternimmt Ihr Server zusätzliche Anstrengungen, um Idempotenz zu garantieren, aber er macht keine Werbung dafür. Browser warnen den Benutzer weiterhin, wenn sie versuchen, eine solche POST-Anforderung neu zu laden.
Tobu
47
@Schneider POST kann eine untergeordnete Ressource erstellen. Daher können Sie POST zur Erfassung senden, z. B. POST / Spesenabrechnungen, und es werden so viele Entitäten (Spesenabrechnungen) auf Ihrem Server erstellt, wie die Anzahl der von Ihnen gesendeten Anforderungen, selbst wenn diese vollständig ähnlich sind. Stellen Sie sich vor, Sie fügen dieselbe Zeile mit dem automatisch inkrementierten Primärschlüssel in die DB-Tabelle (/ Spesenabrechnungen) ein. Die Daten bleiben gleich, der Schlüssel (in diesem Fall URI) wird vom Server generiert und unterscheidet sich für jede andere Einfügung (Anforderung). So POST Effekt kann sein idempotent, aber auch kann es nicht. Daher ist POST nicht idempotent.
Snifff
11
Nehmen wir an, wir haben Entitäten, die zwei Eigenschaften haben können - nameund date. Wenn wir eine Entität mit einer vorhandenen Entität haben nameund datedann Anfragen an sie stellen und nur a angeben, namebesteht das richtige Verhalten von PUT darin, datedie Entität zu löschen , während POST möglicherweise nur die angegebenen Eigenschaften aktualisiert und die nicht spezifizierten Eigenschaften unverändert lässt bevor die Anfrage gestellt wurde. Klingt das richtig / vernünftig oder ist es eine missbräuchliche Verwendung von PUT (ich habe Verweise auf PATCH gesehen , was angemessener erscheint, aber noch nicht existiert)?
Jon z
707
  • POST an eine URL erstellt eine untergeordnete Ressource an einer vom Server definierten URL.
  • Durch PUT an eine URL wird die Ressource in ihrer Gesamtheit unter der vom Client definierten URL erstellt / ersetzt .
  • PATCH to a URL aktualisiert einen Teil der Ressource unter dieser vom Client definierten URL.

Die relevante Spezifikation für PUT und POST ist RFC 2616 §9.5ff.

POST erstellt eine untergeordnete Ressource . POST /itemserstellt also eine Ressource, die unter der /itemsRessource gespeichert ist. Z.B. /items/1. Durch zweimaliges Senden desselben Postpakets werden zwei Ressourcen erstellt.

PUT dient zum Erstellen oder Ersetzen einer Ressource unter einer dem Client bekannten URL .

Deshalb: PUT ist nur ein Kandidat für CREATE, bei dem der Client die URL bereits kennt, bevor die Ressource erstellt wird. Z.B. /blogs/nigel/entry/when_to_use_post_vs_putals Titel wird als Ressourcenschlüssel verwendet

PUT ersetzt die Ressource unter der bekannten URL, falls sie bereits vorhanden ist. Das zweimalige Senden derselben Anforderung hat also keine Auswirkung. Mit anderen Worten, Aufrufe von PUT sind idempotent .

Der RFC lautet wie folgt:

Der grundlegende Unterschied zwischen den POST- und PUT-Anforderungen spiegelt sich in der unterschiedlichen Bedeutung des Anforderungs-URI wider. Der URI in einer POST-Anforderung gibt die Ressource an, die die eingeschlossene Entität verarbeitet. Diese Ressource kann ein Datenakzeptanzprozess, ein Gateway zu einem anderen Protokoll oder eine separate Entität sein, die Anmerkungen akzeptiert. Im Gegensatz dazu identifiziert der URI in einer PUT-Anforderung die der Anforderung beigefügte Entität. Der Benutzeragent weiß, welcher URI beabsichtigt ist, und der Server darf NICHT versuchen, die Anforderung auf eine andere Ressource anzuwenden. Wenn der Server möchte, dass die Anforderung auf einen anderen URI angewendet wird,

Hinweis: PUT wurde hauptsächlich zum Aktualisieren von Ressourcen verwendet (indem sie vollständig ersetzt wurden). In letzter Zeit gibt es jedoch eine Tendenz zur Verwendung von PATCH zum Aktualisieren vorhandener Ressourcen, da PUT angibt, dass es die gesamte Ressource ersetzt. RFC 5789.

Update 2018 : Es gibt einen Fall, der gemacht werden kann, um PUT zu vermeiden. Siehe "REST ohne PUT"

Bei der Technik „REST ohne PUT“ besteht die Idee darin, dass Verbraucher gezwungen sind, neue 'nicht genannte' Anforderungsressourcen zu veröffentlichen. Wie bereits erwähnt, ist das Ändern der Postanschrift eines Kunden ein POST in eine neue Ressource "ChangeOfAddress" und kein PUT einer Ressource "Kunde" mit einem anderen Feldwert für die Postanschrift.

entnommen aus REST API Design - Ressourcenmodellierung von Prakash Subramaniam von Thoughtworks

Dies zwingt die API, Probleme beim Statusübergang zu vermeiden, wenn mehrere Clients eine einzelne Ressource aktualisieren, und passt besser zu Event Sourcing und CQRS. Wenn die Arbeit asynchron ausgeführt wird, erscheint es angemessen, die Transformation zu POSTEN und darauf zu warten, dass sie angewendet wird.

Nigel Thorne
quelle
53
Oder von der anderen Seite des Zauns: PUT, wenn der Client die Adresse der resultierenden Ressource ermittelt, POST, wenn der Server dies tut.
DanMan
3
Ich denke, dass diese Antwort bearbeitet werden sollte, um klarer zu machen, worauf @DanMan auf sehr einfache Weise hingewiesen hat. Was ich hier am wertvollsten finde, ist der Hinweis am Ende, dass ein PUT nur zum Ersetzen der gesamten Ressource verwendet werden sollte.
Hermes
3
PATCH ist seit mindestens einigen Jahren keine realistische Option, aber ich stimme der Ideologie zu.
Crush
4
Ich versuche zu verstehen, aber die Verwendung von PUT zum Erstellen von etwas wäre nur dann sinnvoll, wenn der Client sicher weiß, dass die Ressource noch nicht vorhanden ist, oder? Angenommen, Sie haben in ein paar Jahren Hunderte von Blog-Posts erstellt und dann versehentlich denselben Titel wie vor zwei Jahren für einen Post ausgewählt. Jetzt haben Sie diesen Beitrag ersetzt, der nicht beabsichtigt war. Die Verwendung von PUT zum Erstellen würde also erfordern, dass der Kunde nachverfolgt, was genommen wird und was nicht, und könnte zu Unfällen und unbeabsichtigten Nebenwirkungen führen sowie Routen haben, die zwei völlig unterschiedliche Dinge tun?
GalaxyAbstractor
5
Du hast Recht. Wenn Sie einen Blog-Beitrag mit derselben URL wie einen vorhandenen veröffentlichen, wird dieser vorhandene Beitrag aktualisiert (obwohl Sie dies natürlich zuerst mit einem GET überprüfen könnten). Dies zeigt an, warum es eine schlechte Idee wäre, nur den Titel als URL zu verwenden. Es würde jedoch überall dort funktionieren, wo es einen natürlichen Schlüssel in den Daten gibt ... was meiner Erfahrung nach selten ist. Oder wenn Sie GUIDs verwendet haben
Nigel Thorne
221

Zusammenfassung:

Erstellen:

Kann mit PUT oder POST folgendermaßen durchgeführt werden:

STELLEN

Erstellt DIE neue Ressource mit newResourceId als Bezeichner unter dem URI / resources oder der Auflistung .

PUT /resources/<newResourceId> HTTP/1.1 

POST

Erstellt eine neue Ressource unter dem URI / resources oder der Sammlung . Normalerweise wird die Kennung vom Server zurückgegeben.

POST /resources HTTP/1.1

Aktualisieren:

Kann nur mit PUT folgendermaßen durchgeführt werden:

STELLEN

Aktualisiert die Ressource mit der vorhandenen Ressourcen-ID als Kennung unter dem URI / resources oder der Auflistung .

PUT /resources/<existingResourceId> HTTP/1.1

Erläuterung:

Wenn mit REST und URI als allgemeine tun haben , haben Sie generic auf der linken und bestimmten auf der rechten . Die Generika werden normalerweise als Sammlungen bezeichnet, und die spezifischeren Elemente können als Ressource bezeichnet werden . Beachten Sie, dass eine Ressource eine Sammlung enthalten kann .

Beispiele:

<- generisch - spezifisch ->

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

Wenn Sie POST verwenden, beziehen Sie sich immer auf eine Sammlung . Wenn Sie also sagen:

POST /users HTTP/1.1

Sie einen neuen Benutzer die Entsendung Benutzer Sammlung .

Wenn Sie fortfahren und so etwas versuchen:

POST /users/john HTTP/1.1

es wird funktionieren, aber Sie sagen , dass Sie eine Ressource zu dem semantisch hinzufügen möchten john Sammlung unter der Benutzer Sammlung .

Sobald Sie PUT verwenden, verweisen Sie auf eine Ressource oder ein einzelnes Element, möglicherweise innerhalb einer Sammlung . Also wenn du sagst:

PUT /users/john HTTP/1.1

Sie sind mit dem Server - Update zu sagen, oder erstellen , wenn es das nicht existiert, john Ressource unter dem Benutzer Sammlung .

Spezifikation:

Lassen Sie mich einige wichtige Teile der Spezifikation hervorheben:

POST

Die POST- Methode wird verwendet, um anzufordern, dass der Ursprungsserver die in der Anforderung enthaltene Entität als neuen Untergebenen der durch den Anforderungs-URI in der Anforderungszeile identifizierten Ressource akzeptiert

Erstellt daher eine neue Ressource für eine Sammlung .

STELLEN

Die PUT- Methode fordert an, dass die eingeschlossene Entität unter dem angegebenen Anforderungs-URI gespeichert wird . Wenn sich der Anforderungs-URI auf eine bereits vorhandene Ressource bezieht, MUSS die eingeschlossene Entität als modifizierte Version der auf dem Ursprungsserver befindlichen Entität betrachtet werden. Wenn der Request-URI nicht zu einer bestehenden Punkt nicht Ressource, und dass URI ist fähig als eine definiert wurde neue Ressource von dem anfordernden User - Agenten, der Ursprungsserver kann erstellen die Ressource mit dem URI.“

Erstellen oder aktualisieren Sie daher basierend auf dem Vorhandensein der Ressource .

Referenz:

7hi4g0
quelle
11
Dieser Beitrag war hilfreich für mich, um zu verstehen, dass POST der angegebenen Sammlung (URI) als untergeordnetes Element "etwas" hinzufügt, während PUT das "etwas" am angegebenen URI-Speicherort explizit definiert.
Kwah
3
Dies ist die beste Antwort, hier denke ich: Keiner dieser Unsinn "POST kann eine Ressource aktualisieren". Ich mag Ihre Aussage "Update kann nur mit PUT durchgeführt werden".
Thomas
4
Nein, PUT ist nicht zum Aktualisieren oder Erstellen vorgesehen. Es ist zum Ersetzen. Beachten Sie, dass Sie für den Effekt des Erstellens nichts durch etwas ersetzen können.
Thecoshman
2
@ 7hi4g0 PUT dient zum Aktualisieren mit einem vollständigen Ersatz, dh es ersetzt. Sie ersetzen nichts durch etwas oder etwas durch ein völlig neues Etwas. PUT dient nicht zum Vornehmen einer geringfügigen Änderung (es sei denn, der Client nimmt diese geringfügige Änderung vor und stellt die gesamte neue Version bereit, auch wenn diese gleich bleibt). Für eine teilweise Modifikation ist PATCH die Methode der Wahl.
Thecoshman
1
@thecoshman Sie könnten, aber es wäre nicht zu klar, dass create auch dort behandelt wird. In diesem Fall ist es besser, explizit zu sein.
7hi4g0
175

POST bedeutet "neu erstellen" wie in "Hier ist die Eingabe zum Erstellen eines Benutzers, erstellen Sie es für mich".

PUT bedeutet "einfügen, ersetzen, falls bereits vorhanden" wie in "Hier sind die Daten für Benutzer 5".

POSTWenn Sie auf example.com/users gehen, da Sie URLden Benutzer noch nicht kennen , möchten Sie, dass der Server ihn erstellt.

Sie gehen PUTzu example.com/users/id, da Sie einen bestimmten Benutzer ersetzen / erstellen möchten .

Wenn Sie zweimal mit denselben Daten posten, werden zwei identische Benutzer mit unterschiedlichen IDs erstellt. Durch zweimaliges PUT mit denselben Daten wird der Benutzer zum ersten Mal erstellt und beim zweiten Mal auf den gleichen Status aktualisiert (keine Änderungen). Da Sie nach einer PUTbeliebigen Anzahl von Spielen denselben Zustand haben, wird er jedes Mal als "gleich stark" bezeichnet - idempotent. Dies ist nützlich, um Anforderungen automatisch erneut zu versuchen. Nicht mehr "Sind Sie sicher, dass Sie erneut senden möchten", wenn Sie die Zurück-Taste im Browser drücken.

Ein allgemeiner Rat ist, POSTwenn der Server die Kontrolle über die URLGenerierung Ihrer Ressourcen haben soll. Verwenden Sie PUTsonst. Lieber lieber PUT als POST.

Alexander Torstling
quelle
12
Schlamperei kann dazu geführt haben, dass allgemein gelehrt wird, dass Sie nur zwei Verben benötigen: GET und POST. GET zu erhalten, POST zu ändern. Sogar PUT und DELETE wurden mit POST durchgeführt. Die Frage, was PUT 25 Jahre später wirklich bedeutet, ist vielleicht ein Zeichen dafür, dass wir es zuerst falsch gelernt haben. Die Popularität von REST brachte die Leute zurück zu den Grundlagen, wo wir jetzt schlechte Fehler der Vergangenheit verlernen müssen. POST wurde überbeansprucht und jetzt häufig falsch unterrichtet. Das Beste daran: "Wenn Sie zweimal mit denselben Daten posten, werden zwei identische [Ressourcen] erstellt." Toller Punkt!
Maxpolk
1
Wie können Sie mit PUT einen Datensatz anhand der ID erstellen, wie in Ihrem Beispiel, user 5wenn er noch nicht vorhanden ist? Meinst du nicht update, replace if already exists? oder so
Luke
@Coulton: Ich meinte, was ich geschrieben habe. Sie fügen Benutzer 5 ein, wenn Sie auf / users / 5 setzen und # 5 noch nicht vorhanden ist.
Alexander Torstling
@Coulton: PUTKann auch verwendet werden, um den Wert einer vorhandenen Ressource in ihrer Gesamtheit zu ersetzen .
DavidRR
1
"Bevorzugen Sie PUT gegenüber POST" ... möchten Sie das rechtfertigen?
Thecoshman
173

Ich möchte meinen "pragmatischen" Rat hinzufügen. Verwenden Sie PUT, wenn Sie die "ID" kennen, mit der das zu speichernde Objekt abgerufen werden kann. Die Verwendung von PUT funktioniert nicht so gut, wenn Sie beispielsweise eine datenbankgenerierte ID benötigen, die zurückgegeben werden muss, damit Sie zukünftige Suchvorgänge oder Aktualisierungen durchführen können.

Also: So speichern Sie einen vorhandenen Benutzer oder einen, bei dem der Client die ID generiert und überprüft wurde, ob die ID eindeutig ist:

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

Verwenden Sie andernfalls POST, um das Objekt zunächst zu erstellen, und PUT, um das Objekt zu aktualisieren:

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
ThaDon
quelle
17
Eigentlich sollte es so sein POST /users. (Beachten Sie, dass dies /usersPlural ist.) Dies hat zur Folge, dass ein neuer Benutzer erstellt und zu einer untergeordneten Ressource der /usersSammlung gemacht wird.
DavidRR
6
@DavidRR um fair zu sein, wie man mit Gruppen umgeht, ist eine weitere Debatte. GET /usersmacht Sinn, es liest sich wie Sie wollen, aber ich würde mit GET /user/<id>oder POST /user(mit Nutzlast für den neuen Benutzer) einverstanden sein, weil es richtig lautet: "Hol mir Benutzer 5" ist seltsam, aber "Hol mir Benutzer 5" ist natürlicher. Ich würde wahrscheinlich immer noch auf die Seite der Pluralisierung fallen :)
Thecoshman
126

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

PUT    /items/1      #=> update
POST   /items        #=> create
Tim Sullivan
quelle
4
POST /itemsFügt einer bereits definierten Ressource ein neues Element hinzu ('Element'). Es heißt nicht, wie die Antwort sagt, "eine Gruppe erstellen". Ich verstehe nicht, warum dies 12 Stimmen hat.
David J.
Standardmäßig unterstützt Rails das Erstellen einer Gruppe über REST nicht. Um eine Gruppe zu erstellen, mit der ich eine Ressource erstellen meine, müssen Sie dies über den Quellcode tun.
David J.
8
Dies ist eine faire Richtlinie, aber eine übermäßige Vereinfachung. Wie in den anderen Antworten erwähnt, kann jede Methode sowohl zum Erstellen als auch zum Aktualisieren verwendet werden.
Brad Koch
2
Ich stimme der Antwort mit einer geringfügigen Änderung zu. Verwenden Sie POST zum Erstellen und PUT, um die Ressource vollständig zu aktualisieren. Für Teilaktualisierungen können wir PUT oder PATCH verwenden. Nehmen wir an, wir möchten den Status einer Gruppe aktualisieren. Wir können PUT / groups / 1 / status mit dem Status ist die Anforderungsnutzlast oder PATCH / groups / 1 mit den Details über die Aktion in der Nutzlast verwenden
java_geek
2
Es sollte auch klargestellt werden, dass dies PUT /items/42auch für das Erstellen einer Ressource gilt, jedoch nur, wenn der Client das Recht hat, die Ressource zu benennen . (Erlaubt Rails einem Client dieses
Namensprivileg
123

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

Geben Sie hier die Bildbeschreibung ein

Analogie:

  • PUT dh nehmen und setzen, wo es war.
  • POST als Post in der Post senden .

Geben Sie hier die Bildbeschreibung ein

Social Media / Netzwerk-Analogie:

  • In sozialen Medien posten: Wenn wir eine Nachricht posten, wird ein neuer Beitrag erstellt.
  • Setzen (dh bearbeiten) für die Nachricht, die wir bereits gepostet haben.
Premraj
quelle
21
@MobileMon Nein, REST-Methoden sind nicht CRUD.
jlr
1
Ich würde PUT für UPSERTS sagen
Hola Soja Edu Feliz Navidad
@MobileMon no: POST, wenn Sie eine neue Ressource erstellen und den endgültigen Endpunkt nicht kennen, um sie abzurufen. PUT für andere Fälle.
Portekoi
67

REST ist ein sehr hochrangiges Konzept. Tatsächlich wird HTTP überhaupt nicht erwähnt!

Wenn Sie Zweifel an der Implementierung von REST in HTTP haben, können Sie sich jederzeit die AtomPub- Spezifikation (Atom Publication Protocol) ansehen . AtomPub ist ein Standard zum Schreiben von RESTful-Webservices mit HTTP, der von vielen HTTP- und REST-Leuchten entwickelt wurde. Einige Beiträge stammen von Roy Fielding, dem Erfinder von REST und (Mit-) Erfinder von HTTP.

Möglicherweise können Sie AtomPub sogar direkt verwenden. Obwohl es aus der Blogging-Community stammt, ist es in keiner Weise auf das Bloggen beschränkt: Es ist ein generisches Protokoll für die REST-fähige Interaktion mit beliebigen (verschachtelten) Sammlungen beliebiger Ressourcen über HTTP. Wenn Sie Ihre Anwendung als verschachtelte Sammlung von Ressourcen darstellen können, können Sie einfach AtomPub verwenden und müssen sich keine Gedanken darüber machen, ob Sie PUT oder POST verwenden, welche HTTP-Statuscodes zurückgegeben werden sollen und all diese Details.

Dies ist, was AtomPub zur Ressourcenerstellung zu sagen hat (Abschnitt 9.2):

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

Jörg W Mittag
quelle
8
Es ist nichts Falsches daran, PUT das Erstellen von Ressourcen zu erlauben. Beachten Sie jedoch, dass der Client die URL bereitstellt.
Julian Reschke
5
Es ist sehr falsch, PUT das Erstellen von Ressourcen zu erlauben: Der Client gibt die URL an. Das ist die Aufgabe des Servers!
Joshcodes
@Joshcodes Es ist nicht immer die Aufgabe des Servers, Client-IDs zu erstellen. Ich habe zunehmend Designs gesehen, mit denen Clients eine Art UUID als Ressourcen-ID generieren können. Dieses Design eignet sich insbesondere zur Vergrößerung des Maßstabs.
Justin Ohms
@JustinOhms Ich stimme Ihrem Standpunkt zu vom Kunden generierten IDs zu (Randnotiz: Bei allen von mir seit ca. 2008 entwickelten Systemen muss der Kunde die ID als UUID / Guid erstellen). Das bedeutet nicht, dass der Client die URL angeben sollte.
Joshcodes
1
Ja, wenn die Ressource bereits vorhanden ist, verwenden Sie PUT. In fast allen Fällen sollten die Ressourcen jedoch mit POST erstellt werden und der Client sollte die URL nicht angeben. Roy Fielding stimmt dieser Aussage zu FWIW: roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
Joshcodes
61

Die Entscheidung, ob PUT oder POST zum Erstellen einer Ressource auf einem Server mit einer HTTP + REST-API verwendet werden soll, hängt davon ab, wem die URL-Struktur gehört. Wenn der Client die URL-Struktur kennt oder an deren Definition beteiligt ist, ist dies eine unnötige Kopplung, ähnlich den unerwünschten Kopplungen, die durch SOA entstanden sind. Das Entweichen von Kupplungstypen ist der Grund, warum REST so beliebt ist. Daher ist POST die richtige Methode. Es gibt Ausnahmen von dieser Regel, die auftreten, wenn der Client die Kontrolle über die Standortstruktur der von ihm bereitgestellten Ressourcen behalten möchte. Dies ist selten und bedeutet wahrscheinlich, dass etwas anderes nicht stimmt.

An dieser Stelle werden einige Leute argumentieren, dass der Client die URL der Ressource kennt , wenn RESTful-URLs verwendet werden, und daher ein PUT akzeptabel ist. Aus diesem Grund sind kanonische, normalisierte, Ruby on Rails- und Django-URLs wichtig. Schauen Sie sich die Twitter-API an… bla bla bla. Diese Leute müssen verstehen, dass es keine Restful-URL gibt und dass Roy Fielding selbst Folgendes feststellt :

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 Namespace zu steuern. Ermöglichen Sie Servern stattdessen, Clients anzuweisen, wie geeignete URIs erstellt werden sollen, wie dies in HTML-Formularen und URI-Vorlagen der Fall ist, indem Sie diese Anweisungen in Medientypen und Verknüpfungsbeziehungen definieren. [Ein Fehler hier impliziert, dass Clients aufgrund von Out-of-Band-Informationen eine Ressourcenstruktur annehmen, z. B. einen domänenspezifischen Standard, der 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 stellt tatsächlich eine Verletzung von REST dar, da der Server für die URL-Struktur verantwortlich ist und frei entscheiden sollte, wie sie verwendet werden soll, um eine Kopplung zu vermeiden. Wenn dies verwirrt, lesen Sie die Bedeutung der Selbsterkennung für das API-Design.

Die Verwendung von POST zum Erstellen von Ressourcen ist mit einer Entwurfsüberlegung verbunden, da POST nicht idempotent ist. Dies bedeutet, dass das mehrmalige Wiederholen eines POST nicht jedes Mal das gleiche Verhalten garantiert. Dies macht den Leuten Angst, PUT zu verwenden, um Ressourcen zu erstellen, wenn sie dies nicht sollten. Sie wissen, dass es falsch ist (POST ist für CREATE), aber sie tun es trotzdem, weil sie nicht wissen, wie sie dieses Problem lösen sollen. Diese Besorgnis zeigt sich in der folgenden Situation:

  1. Der Client sendet eine neue Ressource an den Server.
  2. Der Server verarbeitet die Anforderung und sendet eine Antwort.
  3. Der Client erhält die Antwort nie.
  4. Der Server weiß nicht, dass der Client die Antwort nicht erhalten hat.
  5. Der Client hat keine URL für die Ressource (daher ist PUT keine Option) und wiederholt den POST.
  6. POST ist nicht idempotent und der Server ...

In Schritt 6 werden die Leute häufig verwirrt, was zu tun ist. Es gibt jedoch keinen Grund, einen Kludge zu erstellen, um dieses Problem zu lösen. Stattdessen kann HTTP wie in RFC 2616 angegeben 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 zulässig, in denen erwartet wird, dass der Benutzer den Konflikt möglicherweise lösen und die Anforderung erneut senden kann. Der Antwortkörper sollte genug enthalten

Informationen, mit denen der Benutzer die Ursache des Konflikts erkennen kann. Im Idealfall würde die Antwortentität genügend Informationen enthalten, damit der Benutzer oder Benutzeragent das Problem beheben kann. Dies ist jedoch möglicherweise nicht möglich und nicht erforderlich.

Konflikte treten am wahrscheinlichsten als Antwort auf eine PUT-Anforderung auf. Wenn beispielsweise die Versionierung verwendet wird und die Entität, die PUT ist, Änderungen an einer Ressource enthält, die mit denen einer früheren Anforderung (von Drittanbietern) in Konflikt stehen, verwendet der Server möglicherweise die Antwort 409, um anzuzeigen, dass die Anforderung nicht abgeschlossen werden kann . In diesem Fall würde die Antwortentität wahrscheinlich eine Liste der Unterschiede zwischen den beiden Versionen in einem Format enthalten, das durch den Antwortinhaltstyp definiert wird.

Die Antwort mit dem Statuscode 409 Conflict ist der richtige Rückgriff, weil :

  • Das Durchführen eines POST von Daten mit einer ID, die mit einer bereits im System vorhandenen Ressource übereinstimmt, ist „ein Konflikt mit dem aktuellen Status der Ressource“.
  • Da es für den Client wichtig ist, zu verstehen, dass der Server über die Ressource verfügt, und geeignete Maßnahmen zu ergreifen. Dies ist eine "Situation (en), in der erwartet wird, dass der Benutzer den Konflikt möglicherweise lösen und die Anforderung erneut senden kann."
  • Eine Antwort, die die URL der Ressource mit der widersprüchlichen ID und die entsprechenden Voraussetzungen für die Ressource enthält, würde "genügend Informationen für den Benutzer oder Benutzeragenten liefern, um das Problem zu beheben", was der Idealfall gemäß RFC 2616 ist.

Update basierend auf der Version von RFC 7231 zum Ersetzen von 2616

RFC 7231 ersetzt 2616 und beschreibt in Abschnitt 4.3.3 die folgende mögliche Antwort für einen POST

Wenn das Ergebnis der Verarbeitung eines POST einer Darstellung einer vorhandenen Ressource entspricht, kann ein Ursprungsserver den Benutzeragenten zu dieser Ressource umleiten, indem er eine 303-Antwort (siehe Andere) mit der Kennung der vorhandenen Ressource im Feld Standort sendet. Dies hat den Vorteil, dass dem Benutzeragenten eine Ressourcenkennung bereitgestellt und die Darstellung über eine Methode übertragen wird, die für das gemeinsame Zwischenspeichern besser geeignet ist, jedoch auf Kosten einer zusätzlichen Anforderung, wenn der Benutzeragent die Darstellung nicht bereits zwischengespeichert hat.

Es kann jetzt verlockend sein, einfach einen 303 zurückzugeben, falls ein POST wiederholt wird. Das Gegenteil ist jedoch der Fall. Die Rückgabe eines 303 wäre nur dann sinnvoll, wenn mehrere Erstellungsanforderungen (unterschiedliche Ressourcen erstellen) denselben Inhalt zurückgeben. Ein Beispiel wäre ein "Danke, dass Sie Ihre Anforderungsnachricht gesendet haben", das der Client nicht jedes Mal neu herunterladen muss. RFC 7231 behauptet weiterhin in Abschnitt 4.2.2, dass POST nicht idempotent sein soll, und behauptet weiterhin, dass POST zum Erstellen verwendet werden sollte.

Weitere Informationen hierzu finden Sie in diesem Artikel .

Joshcodes
quelle
Wäre eine 409-Konfliktantwort der geeignete Code für den Versuch, ein neues Konto mit einem bereits vorhandenen Benutzernamen zu erstellen? Ich habe 409 speziell für die Versionierung von Konflikten verwendet, aber nachdem ich Ihre Antwort gelesen habe, frage ich mich, ob sie nicht für "doppelte" Anforderungen verwendet werden sollte.
Eric B.
@EricB. Ja, in der von Ihnen beschriebenen Situation "aufgrund eines Konflikts mit dem aktuellen Status der Ressource" schlägt der Vorgang fehl. Darüber hinaus ist zu erwarten, dass der Benutzer den Konflikt lösen kann und der Nachrichtentext den Benutzer nur darüber informieren muss, dass der Benutzername bereits vorhanden ist.
Joshcodes
@Joshcodes Kannst du mehr über den Konfliktlösungsprozess sagen? Wenn in diesem Fall der Benutzername bereits vorhanden ist, wird vom Client erwartet, dass er den Endbenutzer zur Eingabe eines anderen Benutzernamens auffordert? Was ist, wenn der Client tatsächlich versucht, den Benutzernamen mithilfe von POST zu ändern? Sollten PUT-Anforderungen weiterhin zum Aktualisieren von Parametern verwendet werden, während POST zum Erstellen von Objekten verwendet wird, unabhängig davon, ob es sich um ein einzelnes oder mehrere Objekte handelt? Vielen Dank.
BFar
@ BFar2 Wenn der Benutzername bereits vorhanden ist, sollte der Client den Benutzer dazu auffordern. Um den Benutzernamen zu ändern, wird PUT verwendet, da Sie korrekt sind, POST wird zum Erstellen verwendet, immer und PUT für Aktualisierungen, vorausgesetzt, der Benutzername ist Teil einer bereits erstellten Ressource, die geändert werden muss.
Joshcodes
Das Erklären von Dingen mit einer kurzen und effektiven Sprache ist ebenfalls eine wünschenswerte Fähigkeit
Junchen Liu
53

Ich mag diesen Rat aus der Definition von PUT in RFC 2616 :

Der grundlegende Unterschied zwischen den POST- und PUT-Anforderungen spiegelt sich in der unterschiedlichen Bedeutung des Anforderungs-URI wider. Der URI in einer POST-Anforderung gibt die Ressource an, die die eingeschlossene Entität verarbeitet. Diese Ressource kann ein Datenakzeptanzprozess, ein Gateway zu einem anderen Protokoll oder eine separate Entität sein, die Anmerkungen akzeptiert. Im Gegensatz dazu identifiziert der URI in einer PUT-Anforderung die der Anforderung beigefügte Entität. Der Benutzeragent weiß, welcher URI beabsichtigt ist, und der Server darf NICHT versuchen, die Anforderung auf eine andere Ressource anzuwenden.

Dies stimmt mit dem anderen Rat überein, dass PUT am besten auf Ressourcen angewendet wird, die bereits einen Namen haben, und POST ist gut geeignet, um ein neues Objekt unter einer vorhandenen Ressource zu erstellen (und den Server benennen zu lassen).

Ich interpretiere dies und die Idempotenzanforderungen an PUT so, dass:

  • POST eignet sich zum Erstellen neuer Objekte unter einer Sammlung (und create muss nicht idempotent sein).
  • PUT ist gut für die Aktualisierung vorhandener Objekte (und die Aktualisierung muss idempotent sein).
  • POST kann auch für nicht idempotente Aktualisierungen vorhandener Objekte verwendet werden (insbesondere zum Ändern eines Teils eines Objekts ohne Angabe des Ganzen - wenn Sie darüber nachdenken, ist das Erstellen eines neuen Mitglieds einer Sammlung tatsächlich ein Sonderfall dieser Art Update aus Sicht der Sammlung)
  • PUT kann auch nur dann zum Erstellen verwendet werden, wenn Sie dem Client erlauben, die Ressource zu benennen. Da REST-Clients jedoch keine Annahmen über die URL-Struktur treffen sollen, entspricht dies weniger dem beabsichtigten Geist der Dinge.
Metamatt
quelle
3
"POST kann auch für nicht idempotente Aktualisierungen vorhandener Objekte verwendet werden (insbesondere zum Ändern eines Teils eines Objekts, ohne das Ganze anzugeben". Dafür ist
PATCH
48

Zusamenfassend:

PUT ist idempotent, wobei der Ressourcenzustand derselbe ist, wenn dieselbe Operation einmal oder mehrmals ausgeführt wird.

POST ist nicht idempotent, wobei der Ressourcenzustand möglicherweise anders wird, wenn die Operation im Vergleich zur einmaligen Ausführung mehrmals ausgeführt wird.

Analogie zur Datenbankabfrage

PUT Sie können sich ähnlich wie "UPDATE STUDENT SET address =" abc "vorstellen, wobei id =" 123 ";

POST Sie können sich so etwas wie "INSERT IN STUDENT (Name, Adresse) VALUES (" abc "," xyzzz ") vorstellen;

Die Studenten-ID wird automatisch generiert.

Wenn bei PUT dieselbe Abfrage mehrmals oder einmal ausgeführt wird, bleibt der Status der STUDENT-Tabelle derselbe.

Wenn bei POST dieselbe Abfrage mehrmals ausgeführt wird, werden mehrere Student-Datensätze in der Datenbank erstellt, und der Datenbankstatus ändert sich bei jeder Ausführung einer "INSERT" -Abfrage.

HINWEIS: PUT benötigt einen Ressourcenspeicherort (bereits eine Ressource), an dem eine Aktualisierung durchgeführt werden muss, während POST dies nicht erfordert. Daher ist POST intuitiv für die Erstellung einer neuen Ressource gedacht, während PUT für die Aktualisierung der bereits vorhandenen Ressource erforderlich ist.

Einige können sich vorstellen, dass Aktualisierungen mit POST durchgeführt werden können. Es gibt keine feste Regel, welche für Updates oder welche für die Erstellung verwendet werden soll. Auch dies sind Konventionen, und ich neige intuitiv zu den oben genannten Überlegungen und folge ihnen.

Bharatj
quelle
6
für PUT ist ähnlich wie INSERT oder UPDATE Abfrage
Eugen Konkov
1
tatsächlich PUT Sie können sich ähnlich wie "UPDATE STUDENT SET address =" abc "vorstellen, wobei id =" 123 "; wäre eine Anweisung für PATCH." UPDATE STUDENT SET address = "abc", name = "newname" where id = " 123 "wäre eine korrekte Analogie für PUT
mko
Put kann auch für INSERT verwendet werden. Wenn Ihr Server beispielsweise feststellt, dass Sie mehrmals versucht haben, dieselbe Datei hochzuladen, wird Ihre Anfrage dadurch idempotent. (Es werden keine neuen Dateien hochgeladen).
Kiwicomb123
43

POST ist wie das Versenden eines Briefes an eine Mailbox oder das Versenden einer E-Mail an eine E-Mail-Warteschlange. PUT ist wie wenn Sie ein Objekt in ein Ablagefach oder einen Platz in einem Regal legen (es hat eine bekannte Adresse).

Mit POST veröffentlichen Sie an die Adresse der QUEUE oder COLLECTION. Mit PUT setzen Sie an die Adresse des ITEM.

PUT ist idempotent. Sie können die Anfrage 100 Mal senden und es spielt keine Rolle. POST ist nicht idempotent. Wenn Sie die Anfrage 100 Mal senden, erhalten Sie 100 E-Mails oder 100 Briefe in Ihrem Postfach.

Eine allgemeine Regel: Wenn Sie die ID oder den Namen des Elements kennen, verwenden Sie PUT. Wenn Sie möchten, dass die ID oder der Name des Artikels von der empfangenden Partei zugewiesen wird, verwenden Sie POST.

POST versus PUT

Homer6
quelle
1
Nein, PUT impliziert, dass Sie die URL kennen. Wenn Sie nur die ID kennen, POSTEN Sie mit dieser ID, um die URL zu erhalten.
Joshcodes
6
Die ID ist Teil der URL. Verwenden Sie also PUT, wenn Sie die URL kennen (die die ID enthält).
Homer6
Nein, die URL wird vom Server festgelegt und die ID ist nicht unbedingt Teil der URL. Roy Fielding würde Ihnen dasselbe sagen oder Sie könnten einfach seine These lesen .
Joshcodes
@Joshcodes, geht das von REST aus? In einer RESTful-Architektur ist die Element-ID definitiv Teil der URL, wie in: / people / 123. Ich mag diese Seite für REST: microformats.org/wiki/rest/urls
Beez
1
@Beez Der Link mircoformats bietet eine gute Möglichkeit für Server , ihre URLs zu strukturieren, aber der Server bestimmt die URL. Der Client tut dies so gut wie nie. Siehe meine Antwort oder den zugehörigen Artikel, wenn Sie dies nicht verstehen.
Joshcodes
39

Neue Antwort (jetzt, wo ich REST besser verstehe):

PUT ist lediglich eine Aussage darüber, welchen Inhalt der Dienst von nun an verwenden soll, um Darstellungen der vom Client identifizierten Ressource zu rendern. POST ist eine Aussage darüber, welchen Inhalt der Dienst von nun an enthalten soll (möglicherweise dupliziert), aber es ist Sache des Servers, diesen Inhalt zu identifizieren.

PUT x(wenn xeine Ressource identifiziert wird ): "Ersetzen Sie den Inhalt der durch identifizierten Ressource durch xmeinen Inhalt."

PUT x(wenn xkeine Ressource identifiziert wird): "Erstellen Sie eine neue Ressource, die meinen Inhalt enthält, und verwenden Sie sie x, um sie zu identifizieren."

POST x: "Speichern Sie meinen Inhalt und geben Sie mir eine Kennung, mit der ich eine Ressource (alt oder neu) identifizieren kann, die diesen Inhalt enthält (möglicherweise gemischt mit anderen Inhalten). Diese Ressource sollte mit der xidentifizierenden identisch oder untergeordnet sein ." „ Y ‚s Ressource untergeordnet ist x ‘s Ressource“ ist typischerweise aber notwendigerweise , indem sie nicht implementiert y einen Subpfad von x (beispielsweise x = /foound y = /foo/bar) und Modifizieren der Darstellung (e) von x ‚s - Ressource , die Existenz widerzuspiegeln einer neuen Ressource, zB mit einem Hyperlink zu yRessource und einige Metadaten. Nur letzteres ist für ein gutes Design wirklich wichtig, da URLs in REST undurchsichtig sind. Sie sollten Hypermedia anstelle der clientseitigen URL-Konstruktion verwenden, um den Service trotzdem zu durchlaufen.

In REST gibt es keine Ressource, die "Inhalt" enthält. Ich beziehe mich als "Inhalt" auf Daten, die der Dienst verwendet, um Darstellungen konsistent zu rendern. Es besteht normalerweise aus einigen verwandten Zeilen in einer Datenbank oder einer Datei (z. B. einer Bilddatei). Es ist Sache des Dienstes, den Inhalt des Benutzers in etwas zu konvertieren, das der Dienst verwenden kann, z. B. das Konvertieren einer JSON-Nutzlast in SQL-Anweisungen.

Ursprüngliche Antwort (möglicherweise leichter zu lesen) :

PUT /something(falls /somethingbereits vorhanden): "Nimm, was du hast /somethingund ersetze es durch das, was ich dir gebe."

PUT /something(falls /somethingnoch nicht vorhanden): "Nimm was ich dir gebe und lege es an /something."

POST /something: "Nehmen Sie, was ich Ihnen gebe, und platzieren Sie es an einer beliebigen Stelle, /somethingsolange Sie mir die URL geben, wenn Sie fertig sind."

Jordan
quelle
Aber wie können Sie PUT verwenden, um eine neue Ressource zu erstellen, wenn diese nicht vorhanden ist, während Ihre ID-Generierungsmethode auf Auto Increment eingestellt ist? Normalerweise generieren ORMs die ID automatisch für Sie, wie Sie es beispielsweise in einem POST möchten. Bedeutet dies, dass Sie Ihre automatische ID-Generierung ändern müssen, wenn Sie PUT richtig implementieren möchten? Dies ist umständlich, wenn die Antwort ja lautet.
Roni Axelrad
1
@RoniAxelrad: PUT ist wie eine Datenbankanweisung "INSERT OR UPDATE", bei der Sie den Schlüssel in die Anweisung aufnehmen. Dies gilt nur, wenn Sie keine Kollisionen garantieren können. z.B. Ihre Domain hat einen "natürlichen Schlüssel" oder Sie verwenden einen Guid. POST ist wie das Einfügen in eine Tabelle mit einem automatisch inkrementierenden Schlüssel. Die Datenbank muss Ihnen mitteilen, welche ID sie nach dem Einfügen erhalten hat. Beachten Sie, dass Ihr "INSERT OR UPDATE" alle vorherigen Daten ersetzt, falls vorhanden.
Nigel Thorne
@NigelThorne Danke für deine Antwort. Wenn ich zum Beispiel versuche, eine Buch-ID 10 mit einer URI zu setzen: PUT books / 10. Wenn die Buch-ID 10 nicht vorhanden ist, sollte ich ein Buch mit der ID 10 erstellen, oder? Ich kann den Erstellungs-ID-Zähler jedoch nicht steuern, da er automatisch erhöht wird. Was soll ich in dieser Situation tun?
Roni Axelrad
1
@RoniAxelrad REST PUT auf eine nicht vorhandene ID ist eine Anforderung an den Server, eine Ressource zu erstellen. Es liegt immer noch am Server zu entscheiden, ob er dies zulassen möchte. Der Server ist verantwortlich. Es kann mit "Nein, das werde ich nicht tun" antworten. Sie tun dies bereits, wenn der Benutzer nicht über genügend Berechtigungen verfügt ... usw. Es ist in Ordnung, wenn der Server "Nein" sagt. REST ist eine Konvention, mit der wir die Bedeutung verschiedener Arten von Anforderungen definieren können ... Ihr Server entscheidet basierend auf Ihrer Geschäftslogik, was mit diesen Anforderungen geschehen soll :) Auch wenn "Nein" steht, folgt er immer noch REST :)
Nigel Thorne
38

Kurze Antwort:

Einfache Faustregel: Verwenden Sie POST zum Erstellen und PUT zum Aktualisieren.

Lange Antwort:

POST:

  • POST wird verwendet, um Daten an den Server zu senden.
  • Nützlich, wenn die URL der Ressource unbekannt ist

STELLEN:

  • PUT wird verwendet, um den Status auf den Server zu übertragen
  • Nützlich, wenn die URL einer Ressource bekannt ist

Längere Antwort:

Um es zu verstehen, müssen wir uns fragen, warum PUT erforderlich war und welche Probleme PUT zu lösen versuchte, die POST nicht lösen konnte.

Aus Sicht einer REST-Architektur ist nichts von Bedeutung. Wir hätten auch ohne PUT leben können. Aus Sicht eines Kundenentwicklers hat dies sein Leben jedoch viel einfacher gemacht.

Vor dem PUT konnten Clients die vom Server generierte URL nicht direkt kennen oder ob alle von ihm generierten URLs vorhanden waren oder ob die an den Server zu sendenden Daten bereits aktualisiert wurden oder nicht. PUT entlastete den Entwickler von all diesen Kopfschmerzen. PUT ist idempotent, PUT behandelt die Rennbedingungen und PUT lässt den Client die URL auswählen.

ishandutta2007
quelle
3
Ihre kurze Antwort könnte SEHR falsch sein. HTTP-PUT kann von HTTP-Proxys wiederholt werden. Wenn PUT tatsächlich SQL INSERT ausführt, schlägt es möglicherweise zum zweiten Mal fehl, was bedeutet, dass es ein anderes Ergebnis zurückgibt und daher nicht IDEMPOTENT ist (was den Unterschied zwischen PUT und POST darstellt)
Kamil Tomšík
36

Ruby on Rails 4.0 verwendet die 'PATCH'-Methode anstelle von PUT, um Teilaktualisierungen durchzuführen.

RFC 5789 sagt über PATCH (seit 1995):

Eine neue Methode ist erforderlich, um die Interoperabilität zu verbessern und Fehler zu vermeiden. Die PUT-Methode ist bereits zum Überschreiben einer Ressource mit einem vollständig neuen Text definiert und kann nicht für Teiländerungen wiederverwendet werden. Andernfalls können Proxys und Caches sowie Clients und Server hinsichtlich des Ergebnisses des Vorgangs verwirrt werden. POST wird bereits verwendet, jedoch ohne umfassende Interoperabilität (zum einen gibt es keine Standardmethode, um die Unterstützung des Patch-Formats zu ermitteln). PATCH wurde in früheren HTTP-Spezifikationen erwähnt, aber nicht vollständig definiert.

" Edge Rails: PATCH ist die neue primäre HTTP-Methode für Updates ", erklärt es.

germanlinux
quelle
27

Auf die Gefahr hin, das bereits Gesagte erneut zu wiederholen, scheint es wichtig zu sein, sich daran zu erinnern, dass PUT impliziert, dass der Client beim Erstellen einer Ressource kontrolliert, wie die URL letztendlich aussehen wird . Bei der Wahl zwischen PUT und POST geht es also darum, wie sehr Sie dem Client vertrauen können, dass er die richtige, normalisierte URL bereitstellt, die mit Ihrem URL-Schema übereinstimmt.

Wenn Sie dem Client nicht vollständig vertrauen können, dass er das Richtige tut, ist es besser, POST zu verwenden, um ein neues Element zu erstellen und die URL in der Antwort an den Client zurückzusenden.

Pfannendieb
quelle
2
Ich bin etwas spät dran - aber jemand, der auf einer anderen Website etwas Ähnliches sagt, hat es für mich angeklickt. Wenn Sie eine Ressource erstellen und anstelle eines vom Benutzer zugewiesenen Namens eine automatisch inkrementierte ID als "Kennung" verwenden, sollte es sich um einen POST handeln.
Ixmatus
2
Dies ist nicht ganz richtig - PUT kann weiterhin eine Ressource erstellen, indem auf sie mit einem nicht-kanonischen Namen verwiesen wird, solange der Server in der Antwort einen LocationHeader zurückgibt , der den Namen der kanonischen Ressource enthält.
Ether
1
@Joshcodes vergessen Sie nicht, dass Sie viele URIs haben können, die auf dieselbe zugrunde liegende Ressource verweisen. Was Ether sagte, ist ein guter Rat, der Client kann eine URL eingeben (die möglicherweise semantischer ist PUT /X-files/series/4/episodes/max), und der Server antwortet mit einem URI, der einen kurzen kanonischen eindeutigen Link zu dieser neuen Ressource (dh /X-Ffiles/episodes/91)
bereitstellt
@thecoshman das Problem ist das Problem, dass die URL-Struktur nicht dem Client gehört. Das Lesen über die Selbstfindung (ebenfalls Teil von REST) ​​kann dies verdeutlichen.
Joshcodes
@Joshcodes Nach dieser Logik sollte ein Client niemals PUT zum Erstellen verwenden, da er sich nicht mit der Bereitstellung der URL befassen sollte. Nun ... es sei denn, der Server hat eine URL für PUT angegeben, an die der Client sie senden möchte ... so etwas wie "PUT / Kommentare / Neu" und der Server antwortet möglicherweise "204 / Kommentare / 234532", aber das scheint ein bisschen RPC für mich, der Client sollte nur POST an / Kommentare ...
Thecoshman
24

Auf sehr einfache Weise nehme ich das Beispiel der Facebook-Timeline.

Fall 1: Wenn Sie etwas auf Ihrer Timeline veröffentlichen, ist es ein neuer Eintrag. In diesem Fall verwenden sie die POST-Methode, da die POST-Methode nicht idempotent ist.

Fall 2: Wenn Ihr Freund Ihren Beitrag zum ersten Mal kommentiert, wird dadurch auch ein neuer Eintrag in der Datenbank erstellt, sodass die POST-Methode verwendet wird.

Fall 3: Wenn Ihr Freund seinen Kommentar bearbeitet, hatte er in diesem Fall eine Kommentar-ID, sodass er einen vorhandenen Kommentar aktualisiert, anstatt einen neuen Eintrag in der Datenbank zu erstellen. Verwenden Sie daher für diese Art von Operation die PUT-Methode, da sie idempotent ist. *

Verwenden Sie in einer einzelnen Zeile POST , um einen neuen Eintrag in der Datenbank hinzuzufügen, und PUT , um etwas in der Datenbank zu aktualisieren .

UniCoder
quelle
4
Wenn der Kommentar ein Objekt mit einer Eigenschaft wie Benutzer-ID, Erstellungsdatum, Kommentar-Nachricht usw. ist und zum Zeitpunkt der Bearbeitung nur die Kommentar-Nachricht aktualisiert wird, sollte PATCH hier ausgeführt werden?
Habeeb Perwad
PUT wird von FB verwendet, um den Kommentar zu aktualisieren, da eine vorhandene Ressource aktualisiert wird, und genau das tut PUT (aktualisiert eine Ressource). PUT ist im Gegensatz zu POST zufällig idempotent. Ein idempotentes HTTP-Verb wirkt sich auf die Fehlerbehandlung aus, diktiert jedoch nicht die Verwendung. Siehe meine Antwort für eine detailliertere Erklärung: stackoverflow.com/questions/630453/put-vs-post-in-rest/…
Joshcodes
21

Die wichtigste Überlegung ist die Zuverlässigkeit . Wenn eine POST-Nachricht verloren geht, ist der Status des Systems undefiniert. Eine automatische Wiederherstellung ist nicht möglich. Bei PUT-Nachrichten ist der Status nur bis zur ersten erfolgreichen Wiederholung undefiniert.

Beispielsweise ist es möglicherweise keine gute Idee, Kreditkartentransaktionen mit POST zu erstellen.

Wenn Ihre Ressource zufällig automatisch generierte URIs enthält, können Sie PUT weiterhin verwenden, indem Sie einen generierten URI (der auf eine leere Ressource verweist) an den Client übergeben.

Einige andere Überlegungen:

  • POST macht zwischengespeicherte Kopien der gesamten enthaltenen Ressource ungültig (bessere Konsistenz)
  • PUT-Antworten können nicht zwischengespeichert werden, während POST-Antworten vorhanden sind (Content-Location und Ablauf erforderlich).
  • PUT wird beispielsweise von Java ME, älteren Browsern und Firewalls weniger unterstützt
Hans Malherbe
quelle
Das ist falsch. Für POST ist der Status auch nur bis zum ersten erfolgreichen Wiederholungsversuch undefiniert . Dann akzeptiert der Server entweder den POST (Nachricht nie angekommen), löst einen 409-Konflikt für eine doppelte ID aus (Nachricht angekommen, Antwort verloren) oder eine andere gültige Antwort.
Joshcodes
Im Allgemeinen kann ein Benutzeragent den POST-Vorgang nicht sicher wiederholen, da der POST-Vorgang keine Garantie dafür bietet, dass zwei Vorgänge den gleichen Effekt wie einer haben. Der Begriff "ID" hat nichts mit HTTP zu tun. Der URI identifiziert die Ressource.
Hans Malherbe
Ein Useragent kann einen POST-Vorgang "sicher" so oft wiederholen, wie er möchte. Es wird nur ein doppelter ID-Fehler (vorausgesetzt, die Ressource hat eine ID) oder ein doppelter Datenfehler (vorausgesetzt, dies ist ein Problem und die Ressource hat keine IDs) empfangen .
Joshcodes
Pony Kopf gegen Wand. HTTP hat keine Lösung für das Problem der Zuverlässigkeit, und dies ist nicht gut verstanden, wird nicht viel diskutiert und wird in der überwiegenden Mehrheit der Webanwendungen einfach nicht berücksichtigt. @ Joshcodes Ich habe eine Antwort auf diese Frage. Ich stimme Hans im Wesentlichen zu. Es gibt ein Problem.
Bbsimonbb
@bbsimonbb, HTTP verfügt über eine robuste und gut dokumentierte Reihe von Fehlerantworten. Meine Antwort auf diese Frage ( stackoverflow.com/questions/630453/put-vs-post-in-rest/… ) behandelt die Verwendung von http gemäß Spezifikation, um Konsistenz zu erreichen.
Joshcodes
17

Leser, die neu in diesem Thema sind, werden von der endlosen Diskussion darüber, was Sie tun sollten , und dem relativen Fehlen von Lehren aus der Erfahrung beeindruckt sein. Die Tatsache, dass REST gegenüber SOAP "bevorzugt" wird, ist vermutlich ein Lernen auf hohem Niveau aus Erfahrung, aber meine Güte, wir müssen von dort aus Fortschritte gemacht haben? Es ist 2016. Roys Dissertation war im Jahr 2000. Was haben wir entwickelt? Hat es Spaß gemacht? War es einfach zu integrieren? Zu unterstützen? Wird es den Aufstieg von Smartphones und flockigen Mobilfunkverbindungen bewältigen?

Laut ME sind reale Netzwerke unzuverlässig. Fordert eine Zeitüberschreitung an. Verbindungen werden zurückgesetzt. Netzwerke fallen stunden- oder tagelang aus. Züge fahren mit mobilen Benutzern an Bord in Tunnel. Für jede gegebene Anfrage (wie gelegentlich in all diesen Diskussionen bestätigt) kann die Anfrage auf ihrem Weg ins Wasser fallen, oder die Antwort kann auf dem Rückweg ins Wasser fallen. Unter diesen Umständen war es für mich immer etwas brutal und naiv, PUT-, POST- und DELETE-Anfragen direkt gegen materielle Ressourcen zu stellen.

HTTP unternimmt nichts, um einen zuverlässigen Abschluss der Anforderungsantwort sicherzustellen, und das ist in Ordnung, da dies die Aufgabe netzwerkfähiger Anwendungen ist. Wenn Sie eine solche Anwendung entwickeln, können Sie durch die Rahmen springen, um PUT anstelle von POST zu verwenden, und dann durch weitere Rahmen, um eine bestimmte Art von Fehler auf dem Server zu melden, wenn Sie doppelte Anforderungen erkennen. Zurück auf dem Client müssen Sie dann durch die Rahmen springen, um diese Fehler zu interpretieren, erneut abzurufen, erneut zu validieren und erneut zu veröffentlichen.

Oder Sie können dies tun : Betrachten Sie Ihre unsicheren Anforderungen als kurzlebige Einzelbenutzerressourcen (nennen wir sie Aktionen). Clients fordern eine neue "Aktion" für eine inhaltliche Ressource mit einem leeren POST an die Ressource an. POST wird nur dafür verwendet. Sobald der Client sicher im Besitz des URI der frisch geprägten Aktion ist, sendet er die unsichere Anforderung an den Aktions-URI und nicht an die Zielressource . Das Auflösen der Aktion und das Aktualisieren der "echten" Ressource ist ordnungsgemäß Aufgabe Ihrer API und hier vom unzuverlässigen Netzwerk entkoppelt.

Der Server erledigt das Geschäft, gibt die Antwort zurück und speichert sie anhand des vereinbarten Aktions-URI . Wenn etwas schief geht, wiederholt der Client die Anforderung (natürliches Verhalten!), Und wenn der Server sie bereits gesehen hat, wiederholt er die gespeicherte Antwort und unternimmt nichts anderes .

Sie werden die Ähnlichkeit mit Versprechungen schnell erkennen: Wir erstellen den Platzhalter für das Ergebnis und geben ihn zurück, bevor wir etwas unternehmen. Ebenso wie ein Versprechen kann eine Aktion einmal erfolgreich sein oder fehlschlagen, aber das Ergebnis kann wiederholt abgerufen werden.

Das Beste ist, dass wir sendenden und empfangenden Anwendungen die Möglichkeit geben, die eindeutig identifizierte Aktion mit der Eindeutigkeit in ihrer jeweiligen Umgebung zu verknüpfen. Und wir können anfangen, verantwortungsbewusstes Verhalten von Kunden zu fordern und durchzusetzen: Wiederholen Sie Ihre Anfragen so oft Sie möchten, aber generieren Sie keine neue Aktion, bis Sie über ein endgültiges Ergebnis der vorhandenen verfügen.

Als solche verschwinden zahlreiche heikle Probleme. Wiederholte Einfügeanforderungen erzeugen keine Duplikate, und wir erstellen die eigentliche Ressource erst, wenn wir im Besitz der Daten sind. (Datenbankspalten können nicht nullwertfähig bleiben). Wiederholte Aktualisierungsanforderungen treffen nicht auf inkompatible Zustände und überschreiben nachfolgende Änderungen nicht. Clients können die ursprüngliche Bestätigung aus irgendeinem Grund (erneut) abrufen und nahtlos verarbeiten (Client stürzte ab, Antwort ging verloren usw.).

Aufeinanderfolgende Löschanforderungen können die ursprüngliche Bestätigung anzeigen und verarbeiten, ohne dass ein 404-Fehler auftritt. Wenn die Dinge länger dauern als erwartet, können wir vorläufig reagieren und haben einen Ort, an dem der Kunde das endgültige Ergebnis überprüfen kann. Der schönste Teil dieses Musters ist seine Kung-Fu (Panda) -Eigenschaft. Wir nehmen eine Schwäche, die Neigung der Kunden, eine Anfrage zu wiederholen, wenn sie die Antwort nicht verstehen, und verwandeln sie in eine Stärke :-)

Bevor Sie mir sagen, dass dies nicht RESTful ist, bedenken Sie bitte die zahlreichen Möglichkeiten, wie REST-Prinzipien respektiert werden. Clients erstellen keine URLs. Die API bleibt erkennbar, wenn auch mit einer kleinen Änderung in der Semantik. HTTP-Verben werden entsprechend verwendet. Wenn Sie der Meinung sind, dass dies eine große Änderung ist, kann ich Ihnen aus Erfahrung sagen, dass dies nicht der Fall ist.

Wenn Sie der Meinung sind, dass Sie große Datenmengen speichern müssen, sprechen wir über das Volumen: Eine typische Aktualisierungsbestätigung ist ein Bruchteil eines Kilobytes. HTTP gibt Ihnen derzeit ein oder zwei Minuten Zeit, um endgültig zu antworten. Selbst wenn Sie Aktionen nur eine Woche lang speichern, haben Kunden reichlich Gelegenheit, sich zu informieren. Wenn Sie sehr große Volumes haben, möchten Sie möglicherweise einen dedizierten säurekonformen Schlüsselwertspeicher oder eine In-Memory-Lösung.

bbsimonbb
quelle
1
Wird das Speichern einer Antwort nicht mit dem Aufrechterhalten einer Sitzung vergleichbar sein? Dies würde (horizontale) Skalierungsprobleme verursachen.
Saurabh Harwande
17

Zusätzlich zu den von anderen vorgeschlagenen Unterschieden möchte ich noch einen hinzufügen.

In der POST- Methode können Sie Body-Parameter sendenform-data

Bei der PUT- Methode müssen Sie Body-Parameter einsendenx-www-form-urlencoded

Header Content-Type:application/x-www-form-urlencoded

Demnach können Sie in der PUT- Methode keine Dateien oder mehrteiligen Daten senden

BEARBEITEN

Der Inhaltstyp "application / x-www-form-urlencoded" ist ineffizient, um große Mengen von Binärdaten oder Text mit Nicht-ASCII-Zeichen zu senden. Der Inhaltstyp "Multipart / Formulardaten" sollte zum Senden von Formularen verwendet werden, die Dateien, Nicht-ASCII-Daten und Binärdaten enthalten.

Was bedeutet, wenn Sie einreichen müssen

Dateien, Nicht-ASCII-Daten und Binärdaten

Sie sollten die POST- Methode verwenden

Rohit Dhiman
quelle
3
Warum wurde dies nicht positiv bewertet? Wenn das stimmt, ist dies eine kritische Unterscheidung, nicht wahr?
Iofacture
2
Ich habe es bei der Implementierung der API für das Profil-Update gesehen, das das Hochladen von Benutzerprofilbildern umfasst. Dann habe ich es mit dem Postboten Ajax, PHP Curl und Laravel 5.6 als Backend getestet.
Rohit Dhiman
14

Es scheint immer eine gewisse Verwirrung darüber zu bestehen, wann der HTTP-POST im Vergleich zur HTTP-PUT-Methode für REST-Services verwendet werden soll. 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 den HTTP-Methoden zuordnen kann. Das ist:

Create => HTTP PUT
Retrieve => HTTP GET
Update => HTTP POST
Delete => HTTP DELETE

Es ist wahr, dass das R (etrieve) und D (elete) der CRUD-Operationen direkt auf die HTTP-Methoden GET bzw. DELETE abgebildet werden können. Die Verwirrung liegt jedoch in den Operationen C (reate) und U (update). In einigen Fällen kann der PUT zum Erstellen verwendet werden, während in anderen Fällen ein POST erforderlich ist. Die Mehrdeutigkeit liegt in der Definition einer HTTP-PUT-Methode gegenüber einer HTTP-POST-Methode.

Gemäß den HTTP 1.1-Spezifikationen 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 ein- oder mehrmals an einer Ressource ausgeführt werden kann und immer den gleichen Status dieser Ressource zurückgibt. Während eine nicht idempotente Operation einen geänderten Status der Ressource von einer Anforderung zu einer anderen zurückgeben kann. Daher gibt es bei einer nicht idempotenten Operation keine Garantie dafür, dass einer den gleichen Status einer Ressource erhält.

Basierend auf der obigen idempotenten Definition gehe ich davon aus, dass ich die HTTP-PUT-Methode im Vergleich zur HTTP-POST-Methode für REST-Services verwende: Verwenden Sie die HTTP-PUT-Methode, wenn:

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).

In beiden Fällen können diese Vorgänge mehrmals mit denselben Ergebnissen ausgeführt werden. Das heißt, die Ressource wird nicht geändert, wenn die Operation mehr als einmal angefordert wird. Daher eine echte idempotente Operation. Verwenden Sie die HTTP-POST-Methode, wenn:

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.

Fazit

Korrelieren Sie CRUD-Operationen nicht direkt und ordnen Sie sie HTTP-Methoden für REST-Services zu. Die Verwendung einer HTTP-PUT-Methode im Vergleich zu einer HTTP-POST-Methode sollte auf dem idempotenten Aspekt dieser Operation basieren. Wenn die Operation idempotent ist, verwenden Sie die HTTP-PUT-Methode. Wenn die Operation nicht idempotent ist, verwenden Sie die HTTP-POST-Methode.

Burhan
quelle
2
Update => HTTP POST: POST ist nicht für die Aktualisierung
Premraj
@premraj Du hast die Annahme gemacht, dass Burhan dir sagt, dass du es nicht machen sollst; Sie verbinden nämlich CRUD, REST und HTTP. Wenn Sie RFC 7231 lesen, in dem diese Dinge definiert sind, werden Sie feststellen, dass die Definition von POST im HTTP-Protokoll sicherlich eine Aktualisierung ermöglicht. Es sind nur die Einschränkungen von REST, die etwas anderes aussagen.
IAM_AL_X
13

Der Ursprungsserver kann die Ressource mit diesem URI erstellen

Sie verwenden also POST und wahrscheinlich, aber nicht notwendiges PUT für die Ressourcenerstellung. Sie müssen nicht beide unterstützen. Für mich ist POST perfekt genug. Es ist also eine Designentscheidung.

Wie in Ihrem Zitat erwähnt, verwenden Sie PUT zum Erstellen, da einer IRI keine Ressource zugewiesen ist, und Sie möchten trotzdem eine Ressource erstellen. Beispielsweise wird PUT /users/123/passwordnormalerweise das alte Kennwort durch ein neues ersetzt. Sie können es jedoch verwenden, um ein Kennwort zu erstellen, falls es noch nicht vorhanden ist (z. B. durch frisch registrierte Benutzer oder durch Wiederherstellen gesperrter Benutzer).

inf3rno
quelle
Ich denke, Sie haben es geschafft, eines der wenigen guten Beispiele für die Verwendung von PUT zu liefern, gut gemacht.
Thecoshman
12

Ich werde mit folgendem landen:

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

POST ist im Grunde eine Freiformnachricht, deren Bedeutung "außerhalb des Bandes" definiert wird. Wenn die Nachricht als Hinzufügen einer Ressource zu einem Verzeichnis interpretiert werden kann, wäre dies in Ordnung. Grundsätzlich müssen Sie jedoch die Nachricht verstehen, die Sie senden (veröffentlichen), um zu wissen, was mit der Ressource geschehen wird.


Da sich PUT und GET und DELETE auf eine Ressource beziehen, sind sie per Definition auch idempotent.

POST kann die anderen drei Funktionen ausführen, aber dann geht die Semantik der Anforderung auf den Vermittlern wie Caches und Proxys verloren. Dies gilt auch für die Bereitstellung von Sicherheit für die Ressource, da der URI eines Posts nicht unbedingt die Ressource angibt, auf die er angewendet wird (dies kann jedoch möglich sein).

Ein PUT muss kein Create sein. Der Dienst kann einen Fehler verursachen, wenn die Ressource noch nicht erstellt wurde. Andernfalls wird sie aktualisiert. Oder umgekehrt - es kann die Ressource erstellen, aber keine Updates zulassen. Das einzige, was für PUT erforderlich ist, ist, dass es auf eine bestimmte Ressource verweist und seine Nutzlast die Darstellung dieser Ressource ist. Ein erfolgreicher PUT bedeutet (abgesehen von Interferenzen), dass ein GET dieselbe Ressource abruft.


Bearbeiten: Eine weitere Sache - ein PUT kann erstellen, aber wenn dies der Fall ist, muss die ID eine natürliche ID sein - AKA eine E-Mail-Adresse. Auf diese Weise ist beim zweiten PUT der zweite Put ein Update des ersten. Das macht es idempotent .

Wenn die ID generiert wird (z. B. eine neue Mitarbeiter-ID), erstellt der zweite PUT mit derselben URL einen neuen Datensatz, der gegen die idempotente Regel verstößt. In diesem Fall wäre das Verb POST, und die Nachricht (nicht Ressource) wäre, eine Ressource unter Verwendung der in dieser Nachricht definierten Werte zu erstellen.

Gerard ONeill
quelle
9

Die Semantik soll insofern unterschiedlich sein, als "PUT" wie "GET" idempotent sein soll - das heißt, Sie können dieselbe exakte PUT-Anforderung mehrmals ausführen und das Ergebnis ist so, als hätten Sie sie nur einmal ausgeführt.

Ich werde die Konventionen beschreiben, die meiner Meinung nach am weitesten verbreitet und am nützlichsten sind:

Wenn Sie eine Ressource an eine bestimmte URL setzen, geschieht dies unter dieser URL oder in einer ähnlichen Richtung.

Wenn Sie an eine Ressource unter einer bestimmten URL posten, veröffentlichen Sie häufig eine verwandte Information an diese URL. Dies bedeutet, dass die Ressource unter der URL bereits vorhanden ist.

Wenn Sie beispielsweise einen neuen Stream erstellen möchten, können Sie ihn einer URL hinzufügen. Wenn Sie jedoch eine Nachricht an einen vorhandenen Stream senden möchten, senden Sie sie an die URL.

Das Ändern der Eigenschaften des Streams kann entweder mit PUT oder POST erfolgen. Verwenden Sie "PUT" grundsätzlich nur, wenn die Operation idempotent ist - andernfalls verwenden Sie POST.

Beachten Sie jedoch, dass nicht alle modernen Browser andere HTTP-Verben als GET oder POST unterstützen.

Gregory Magarshak
quelle
Was Sie als POST bezeichnen, ist das Verhalten von PATCH. POST soll etwas ähnlicheres wie "Anhängen" bedeuten als "Post an Mailingliste".
Alexander Torstling
8

Meistens werden Sie sie folgendermaßen verwenden:

  • POST eine Ressource in eine Sammlung
  • PUT eine Ressource, die durch collection /: id identifiziert wird

Zum Beispiel:

  • POST / Artikel
  • PUT / items / 1234

In beiden Fällen enthält der Anforderungshauptteil die Daten für die Ressource, die erstellt oder aktualisiert werden soll. Aus den Routennamen sollte ersichtlich sein, dass POST nicht idempotent ist (wenn Sie es dreimal aufrufen, werden 3 Objekte erstellt), aber PUT ist idempotent (wenn Sie es dreimal aufrufen, ist das Ergebnis dasselbe). PUT wird häufig für "Upsert" -Operationen (Erstellen oder Aktualisieren) verwendet. Sie können jedoch jederzeit einen 404-Fehler zurückgeben, wenn Sie ihn nur zum Ändern verwenden möchten.

Beachten Sie, dass POST ein neues Element in der Sammlung "erstellt" und PUT ein Element unter einer bestimmten URL "ersetzt". Es ist jedoch sehr üblich, PUT für teilweise Änderungen zu verwenden, dh nur zum Aktualisieren vorhandener Ressourcen und zu verwenden Ändern Sie nur die im Text enthaltenen Felder (ignorieren Sie die anderen Felder). Dies ist technisch nicht korrekt. Wenn Sie REST-Purist sein möchten, sollte PUT die gesamte Ressource ersetzen und PATCH für die teilweise Aktualisierung verwenden. Es ist mir persönlich egal, wie klar und konsistent das Verhalten auf allen API-Endpunkten ist.

Denken Sie daran, REST ist eine Reihe von Konventionen und Richtlinien, um Ihre API einfach zu halten. Wenn Sie am Ende eine komplizierte Problemumgehung haben, nur um das Kontrollkästchen "RESTfull" zu aktivieren, haben Sie den Zweck verfehlt;)

tothemario
quelle
7

Während es wahrscheinlich eine agnostische Art gibt, diese zu beschreiben, scheint es im Widerspruch zu verschiedenen Aussagen von Antworten auf Websites zu stehen.

Lassen Sie uns hier sehr klar und direkt sein. Wenn Sie ein .NET-Entwickler sind, der mit der Web-API arbeitet, finden Sie die Fakten (aus der Microsoft API-Dokumentation) unter http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web -api-das-unterstützt-grobe-Operationen :

1. PUT = UPDATE (/api/products/id)
2. MCSD Exams 2014 -  UPDATE = PUT, there are **NO** multiple answers for that question period.

Sicher, Sie können "POST" zum Aktualisieren "verwenden", aber befolgen Sie einfach die für Sie festgelegten Konventionen mit Ihrem vorgegebenen Framework. In meinem Fall handelt es sich um eine .NET / Web-API, daher ist PUT für UPDATE keine Debatte.

Ich hoffe, dies hilft allen Microsoft-Entwicklern, die alle Kommentare mit Links zu Amazon- und Sun / Java-Websites lesen.

Tom Stickel
quelle
7

Hier ist eine einfache Regel:

STELLEN to a URL sollte verwendet werden, um die Ressource zu aktualisieren oder zu erstellen, die sich unter dieser URL befindet.

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

Adam Griffiths
quelle
1
PUT dient nicht zum Aktualisieren, sondern zum Ersetzen. Beachten Sie, dass Sie zum Erstellen nichts durch etwas ersetzen. POST ist absolut nicht für Aktualisierungen in irgendeiner Form geeignet.
Thecoshman
2
Sagt die http-Spezifikation das? Oder stützen Sie Ihren Kommentar auf etwas anderes?
Adam Griffiths
Es ist nur gesunder Menschenverstand, wie Sie etwas aktualisieren, wenn Sie nicht wissen, was Sie aktualisieren? POST dient zum Erstellen einer neuen Ressource.
Thecoshman
2
thecoshman - Sie missbrauchen hier die Semantik - ein Ersatz kann ein Update sein, wenn es sich um dieselbe Ressource handelt, mit einigen Unterschieden. Ein Ersetzen ist nur für Put gültig, wenn Ersetzen verwendet wird, um dieselbe Ressource zu ändern. Das Ersetzen durch eine neue und andere Ressource ist ungültig (alte entfernen und neue hinzufügen?), Insbesondere wenn die 'neue' Ressource keine natürliche ID hat. POST, OTOH, kann erstellt, aktualisiert, ersetzt und gelöscht werden. Die Verwendung von Post hängt davon ab, ob eine zu interpretierende Nachricht vorhanden ist oder nicht, z. B. "Rabatt anwenden", die die Ressource je nach Bedarf ändern kann oder nicht Logik.
Gerard ONeill
Was Ihren zweiten Kommentar betrifft - wie wäre es, wenn Sie die Ressource "erhalten", die Felder ändern, die Sie benötigen, und sie dann zurücksetzen? Oder wie wäre es, wenn die Ressource aus einer anderen Quelle stammt, aber eine natürliche ID (die externe ID) verwendet - put würde die Ressource natürlich unter der URL aktualisieren, wenn sich die ursprünglichen Daten ändern.
Gerard ONeill
6

Wenn Sie mit Datenbankoperationen vertraut sind, gibt es

  1. Wählen
  2. Einfügen
  3. Aktualisieren
  4. Löschen
  5. Zusammenführen (Aktualisieren, falls bereits vorhanden, sonst einfügen)

Ich verwende PUTzum Zusammenführen und Aktualisieren ähnliche Vorgänge und POSTzum Einfügen.

Rajan
quelle
5

In der Praxis eignet sich POST gut zum Erstellen von Ressourcen. Die URL der neu erstellten Ressource sollte im Location-Antwortheader zurückgegeben werden. PUT sollte zum vollständigen Aktualisieren einer Ressource verwendet werden. Bitte haben Sie Verständnis dafür, dass dies die Best Practices beim Entwerfen einer RESTful-API sind. Die HTTP-Spezifikation als solche beschränkt die Verwendung von PUT / POST nicht mit einigen Einschränkungen für das Erstellen / Aktualisieren von Ressourcen. Schauen Sie sich http://techoctave.com/c7/posts/71-twitter-rest-api-dissected an , in dem die Best Practices zusammengefasst sind.

java_geek
quelle
Wenn Sie all diese Geräusche durchlesen, scheinen Sie größtenteils am Ball zu sein. Ich würde jedoch sagen, wir sollten PUT als Ersetzungsmethode und nicht als Erstellen / Aktualisieren bezeichnen. Ich denke, es beschreibt besser in einem, was es tut.
Thecoshman