Erstellen Sie eine Anfrage mit POST, die die Antwortcodes 200 oder 201 und den Inhalt enthält


124

Angenommen, ich schreibe einen REST-Service, dessen Absicht es ist, einem System ein neues Datenelement hinzuzufügen.

Ich habe vor zu POSTEN

http://myhost/serviceX/someResources

Angenommen, das funktioniert. Welchen Antwortcode soll ich verwenden? Und welchen Inhalt könnte ich zurückgeben?

Ich schaue mir die Definitionen von HTTP-Antwortcodes an und sehe diese Möglichkeiten:

200: Gibt eine Entität zurück, die das Ergebnis der Aktion beschreibt oder enthält.

201: was bedeutet ERSTELLT. Bedeutung * Die Anforderung wurde erfüllt und es wurde eine neue Ressource erstellt. Auf die neu erstellte Ressource kann durch die in der Entität der Antwort zurückgegebenen URIs verwiesen werden, wobei der spezifischste URI für die Ressource durch ein Standortheaderfeld angegeben wird. Die Antwort sollte eine Entität enthalten, die eine Liste von Ressourcenmerkmalen und Standorten enthält, aus denen der Benutzer oder Benutzeragent die am besten geeignete auswählen kann. Das Entitätsformat wird durch den im Headerfeld Inhaltstyp angegebenen Medientyp angegeben. * *

Letzteres klingt eher im Einklang mit der HTTP-Spezifikation, aber mir ist überhaupt nicht klar, was

Die Antwort sollte eine Entität enthalten, die eine Liste von Ressourcenmerkmalen und Standorten enthält.

meint.

Empfehlungen? Interpretationen?

Antworten:


77

Die Idee ist, dass der Antworttext Ihnen eine Seite gibt, die Sie mit der Sache verknüpft:

201 Erstellt

Der Statuscode 201 (Erstellt) zeigt an, dass die Anforderung erfüllt wurde und eine oder mehrere neue Ressourcen erstellt wurden. Die durch die Anforderung erstellte primäre Ressource wird entweder durch ein Standortheaderfeld in der Antwort oder, falls kein Standortfeld empfangen wird, durch den effektiven Anforderungs-URI identifiziert.

Dies bedeutet, dass Sie ein Locationin den Antwortheader aufnehmen würden , das die URL angibt, unter der Sie das neu erstellte Objekt finden können :

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597

Antwortkörper

Sie gehen dann zu erwähnen , was Sie in der Antwort enthalten sollte Körper :

Die 201-Antwortnutzdaten beschreiben und verknüpfen normalerweise die erstellten Ressourcen.

Für den Menschen, der den Browser verwendet, geben Sie ihm etwas, das er anzeigen und anklicken kann, um zu seiner neu erstellten Ressource zu gelangen:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: text/html

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

Wenn die Seite nur von einem Roboter verwendet wird, ist es sinnvoll, dass die Antwort computerlesbar ist:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/xml

<createdResources>
   <questionID>1860645</questionID>
   <answerID>36373586</answerID>
   <primary>/a/36373586/12597</primary>
   <additional>
      <resource>http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586</resource>
      <resource>http://stackoverflow.com/a/1962757/12597</resource>
   </additional>
</createdResource>

Oder wenn Sie es vorziehen:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/json

{ 
   "questionID": 1860645, 
   "answerID": 36373586,
   "primary": "/a/36373586/12597",
   "additional": [
      "http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586",
      "http://stackoverflow.com/a/36373586/12597"
   ]
}

Die Antwort liegt ganz bei Ihnen; Es ist willkürlich, was Sie möchten.

Cache freundlich

Schließlich gibt es die Optimierung, dass ich die erstellte Ressource vorab zwischenspeichern kann (weil ich den Inhalt bereits habe; ich habe ihn gerade hochgeladen). Der Server kann ein Datum oder ein ETag zurückgeben, das ich mit dem gerade hochgeladenen Inhalt speichern kann:

In Abschnitt 7.2 finden Sie eine Erläuterung der Bedeutung und des Zwecks von Validator-Header-Feldern wie ETag und Last-Modified in einer 201-Antwort.

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/23704283/12597
Content-Type: text/html
ETag: JF2CA53BOMQGU5LTOQQGC3RAMV4GC3LQNRSS4
Last-Modified: Sat, 02 Apr 2016 12:22:39 GMT 

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

Und ETags sind rein willkürliche Werte. Es kommt nur darauf an, dass sie unterschiedlich sind, wenn sich eine Ressource ändert (und die Caches aktualisiert werden müssen). Das ETag ist normalerweise ein Hash (z. B. SHA2). Es kann sich jedoch um eine Datenbank rowversionoder eine inkrementelle Versionsnummer handeln. Alles , was wird ändern , wenn die Sache ändert.


Bisher scheint Ihre Antwort am sinnvollsten zu sein. Ich bin ein wenig besorgt über die Ontologie der Antwort, aber abgesehen davon scheint es die ausgereifteste Interpretation der Spezifikation zu sein. Ich bin gespannt, ob es eine leichte "reaktionsschnelle" Möglichkeit gibt, mit der Ausgabe von Mensch und Maschine umzugehen. Aber meistens bin ich fasziniert von Ihrem Vorschlag, Ihre eigenen Eingaben zwischenzuspeichern. Die meisten mir bekannten Web-Apps erstellen keine 1: 1-Version der Ressource. Auch wenn es etwas Triviales ist, wie die Normalisierung der Großschreibung eines Strings. Ist es nicht etwas zwielichtig, Ihre eingereichte Version als die Version zu behandeln, für die das Etag erstellt wurde?
Anthony

1
@Anthony, Caching: Es könnte sich um eine Art 1: 1-Dateispeicheranwendung handeln. Vergleiche zB WebDAV PUT & POST. Riesige Dateien müssen bearbeitet werden.
kxr

@Anthony Es liegt an Ihnen, ob Sie einen ETag an den Client zurückgeben möchten. Wenn der Inhalt, den der Client gerade hochgeladen hat, nicht dem entspricht, den Sie gespeichert haben, geben Sie das ETag nicht zurück. Es ist Ihre Flexibilität und Ihre Wahl.
Ian Boyd

Warum fehlt Ihren Antworten die Inhaltslänge?
Vinnie Falco

1
@VinnieFalco Dies ist eine Antwort auf den 201-Antwortcode. Die Inhaltslänge wurde für Expository-Zwecke entfernt.
Ian Boyd

91

Ich denke, die atompub REST API ist ein großartiges Beispiel für einen erholsamen Service. Siehe den folgenden Ausschnitt aus der atompub-Spezifikation:

POST /edit/ HTTP/1.1
Host: example.org
User-Agent: Thingio/1.0
Authorization: Basic ZGFmZnk6c2VjZXJldA==
Content-Type: application/atom+xml;type=entry
Content-Length: nnn
Slug: First Post

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
</entry>

Der Server signalisiert eine erfolgreiche Erstellung mit dem Statuscode 201. Die Antwort enthält einen Standortheader, der den Mitgliedseintrags-URI des Atomeintrags angibt, und eine Darstellung dieses Eintrags im Hauptteil der Antwort.

HTTP/1.1 201 Created
Date: Fri, 7 Oct 2005 17:17:11 GMT
Content-Length: nnn
Content-Type: application/atom+xml;type=entry;charset="utf-8"
Location: http://example.org/edit/first-post.atom
ETag: "c180de84f991g8"  

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
  <link rel="edit"
      href="http://example.org/edit/first-post.atom"/>
</entry>

Der von der Sammlung erstellte und zurückgegebene Eintrag stimmt möglicherweise nicht mit dem vom Client geposteten Eintrag überein. Ein Server kann die Werte verschiedener Elemente im Eintrag ändern, z. B. die Werte atom: id, atom: updated und atom: author, und möglicherweise andere Elemente und Attribute entfernen oder hinzufügen oder den Elementinhalt und die Attributwerte ändern.


9
Das Zurückgeben der erstellten Ressource kann etwas viel sein, wenn die Ressource in der Größenordnung von Gigabyte liegt ...
Tor Valamo

10
Einverstanden! Das ist die Optimierung der Notwendigkeit - aber Sie möchten es nicht vorzeitig tun. Es ist wichtig, in erholsamen Geistern zu entwerfen und Ausnahmen nur dann zu machen, wenn sie notwendig sind.
Chandra Patni

3
@ChandraPatni, Atom ist tot . Brauche bessere Beispiele.
Pacerier

16
Atom mag tot sein, aber der Geist des Beispiels ist immer noch genau richtig.
Ashimema

2
Meine ursprüngliche Interpretation der 201-Antwort lautete eher: "Hey, Sie wollten eine Ressource erstellen, aber basierend auf dem Kontext waren Sie entweder nicht am Endergebnis interessiert oder haben Schreibzugriff, aber keinen Lesezugriff auf diese Ressource. In beiden Fällen In diesem Fall benötigen Sie lediglich die URL der erstellten Ressource, um zur Hauptsammlung zurückzukehren. Als Beweis dafür wurde sie erstellt. " Alles darüber hinaus scheint im Wesentlichen eine Antwort von 200 zu sein. Es sei denn, der RFC hatte etwas anderes im Sinn.
Anthony

49

In wenigen Worten:

  • 200, wenn ein Objekt erstellt und zurückgegeben wird
  • 201 wenn ein Objekt erstellt wird, aber nur seine Referenz zurückgegeben wird (z. B. eine ID oder ein Link)

Quelle dafür?
Sudo Soul


3
Nachdem ich tools.ietf.org/html/rfc7231#section-6.3.1 gelesen habe , stimme ich diesem Verständnis zu - ich glaube, ich habe mehr gefragt, wie Sie dazu gekommen sind. Aber jetzt nach meinem Verständnis ... 200 = Ressource erstellt und zurückgegeben | 201 = Ressource erstellt und Referenz zurückgegeben | 204 = Ressource erstellt und keine Nutzlast zurückgegeben
Sudo Soul

34

Check out HTTP: Methodendefinitionen: POST .

Die von der POST-Methode ausgeführte Aktion führt möglicherweise nicht zu einer Ressource, die durch einen URI identifiziert werden kann. In diesem Fall ist entweder 200 (OK) oder 204 (kein Inhalt) der geeignete Antwortstatus, je nachdem, ob die Antwort eine Entität enthält, die das Ergebnis beschreibt oder nicht.

Wenn eine Ressource auf dem Ursprungsserver erstellt wurde, MUSS die Antwort 201 (Erstellt) sein und eine Entität enthalten, die den Status der Anforderung beschreibt und auf die neue Ressource verweist, sowie einen Standortheader (siehe Abschnitt 14.30).


18

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19

Es ist nur ein durch Doppelpunkte getrennter Schlüsselwert.

ETag: "xyzzy"

Es kann sich um jede Art von Textdaten handeln. Im Allgemeinen füge ich eine JSON-Zeichenfolge mit der Kennung des erstellten Elements hinzu. Allein die Leichtigkeit des Testens macht es lohnenswert, es einzubeziehen.

ETag: "{ id: 1234, uri: 'http://domain.com/comments/1234', type: 'comment' }"

In diesem Beispiel sind der Bezeichner, die URL und der Typ des erstellten Elements die "Ressourcenmerkmale und der Speicherort".


3
Sie sagen, dass ein ETag einer Entität entspricht, die eine Liste von Ressourcenmerkmalen und Standorten enthält . Ich kann sehen, dass Ihr Vorschlag gut ist, und stimme Ihrem Standpunkt zum Testen sehr zu. Ich sehe jedoch nicht, wie dies zu "einer Liste von Ressourcenmerkmalen und Standorten" passt.
DJNA

Die "Liste der Ressourcenmerkmale und -orte" wäre der Inhalt der bereitgestellten Datenstruktur. Eine strengere Implementierung wäre, dass die JSON-Struktur die Ressourcen-URL und möglicherweise den Typ der erstellten Ressource enthält. Ich werde die Antwort als solche anpassen.
Tempire

7
Geben Sie die Probleme an, damit die Benutzer lernen können. Ansonsten winkt der Kommentar nur von Hand.
Tempire

@ SimonGibbs Welche Probleme?
MEMark

2
Obwohl es gemäß der Spezifikation streng korrekt ist, empfiehlt es eine äußerst ungewöhnliche Implementierungsoption. Außerdem wird die Frage oben auf der Seite nicht beantwortet (oder es werden die Wörter ETag und entity verwechselt). Die Antwort mit 43 Stimmen ist wahrscheinlich besser.
Simon Gibbs

1

Die Ausgabe hängt tatsächlich vom angeforderten Inhaltstyp ab. Sie sollten jedoch mindestens die Ressource, die erstellt wurde, in Location ablegen. Genau wie das Post-Redirect-Get-Muster.

In meinem Fall lasse ich es leer, bis ich anders angefordert werde. Da dies das Verhalten von JAX-RS bei Verwendung von Response.created () ist.

Beachten Sie jedoch, dass Browser und Frameworks wie Angular den 201 nicht automatisch folgen. Ich habe das Verhalten in http://www.trajano.net/2013/05/201-created-with-angular-resource/ notiert.


-2

Eine andere Antwort, die ich dafür hätte, wäre, einen pragmatischen Ansatz zu verfolgen und Ihren REST-API-Vertrag einfach zu halten. In meinem Fall hatte ich meine REST-API überarbeitet, um die Testbarkeit zu verbessern, ohne auf JavaScript oder XHR zurückzugreifen, sondern nur auf einfache HTML-Formulare und Links.

Um Ihre Frage oben genauer zu beantworten, würde ich einfach den Rückkehrcode verwenden 200 und lasse die zurückgegebene Nachricht eine JSON-Nachricht enthalten, die Ihre Anwendung verstehen kann. Abhängig von Ihren Anforderungen ist möglicherweise die ID des neu erstellten Objekts erforderlich, damit die Webanwendung die Daten in einem anderen Aufruf abrufen kann.

Ein Hinweis: In meinem überarbeiteten API-Vertrag sollten POST-Antworten keine zwischenspeicherbaren Daten enthalten, da POSTs nicht wirklich zwischengespeichert werden können. Beschränken Sie sie daher auf IDs, die mithilfe einer GET-Anforderung angefordert und zwischengespeichert werden können.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.