Ich entwerfe einen RESTful-Webdienst mit WebApi und frage mich, welche HTTP-Antworten und -Antwortkörper beim Aktualisieren / Erstellen von Objekten zurückgegeben werden sollen.
Zum Beispiel kann ich die POST-Methode verwenden, um JSON an den Webdienst zu senden und dann ein Objekt zu erstellen. Ist es empfehlenswert, den HTTP-Status auf "Erstellt" (201) oder "OK" (200) zu setzen und einfach eine Nachricht wie "Neuer Mitarbeiter hinzugefügt" oder das ursprünglich gesendete Objekt zurückzugeben?
Gleiches gilt für die PUT-Methode. Welcher HTTP-Status ist am besten zu verwenden und muss ich das erstellte Objekt oder nur eine Nachricht zurückgeben? Berücksichtigt man die Tatsache, dass der Benutzer weiß, welches Objekt er ohnehin erstellen / aktualisieren möchte.
Irgendwelche Gedanken?
Beispiel:
Neuen Mitarbeiter hinzufügen:
POST /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Name" : "Joe Bloggs",
"Department" : "Finance"
}
}
Bestehenden Mitarbeiter aktualisieren:
PUT /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
}
Antworten:
Antwort mit Objekt erstellt / aktualisiert
HTTP/1.1 201 Created
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT
{
"Employee": {
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
}
Antwort mit nur einer Nachricht:
HTTP/1.1 200 OK
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT
{
"Message": "Employee updated"
}
Antwort nur mit Statuscode:
HTTP/1.1 204 No Content
Content-Length: 39
Date: Mon, 28 Mar 2016 14:32:39 GMT
UPDATE/INSERT ... RETURNING
Variante für SQL. Es ist äußerst praktisch, zumal es die Übermittlung neuer Daten und die Anforderung der aktualisierten Atomic-Version aufrechterhält.Antworten:
Wie bei den meisten Dingen kommt es darauf an. Ihr Kompromiss ist die Benutzerfreundlichkeit im Verhältnis zur Netzwerkgröße. Es kann für Kunden sehr hilfreich sein, die erstellte Ressource zu sehen. Es kann Felder enthalten, die vom Server ausgefüllt werden, z. B. zum Zeitpunkt der letzten Erstellung. Da Sie anscheinend das einschließen,
id
anstatt es zu verwendenhateoas
, möchten Clients wahrscheinlich die ID für die Ressource sehen, die sie geradePOST
bearbeitet haben.Wenn Sie die erstellte Ressource nicht einschließen, erstellen Sie keine beliebige Nachricht. Die Felder 2xx und Location bieten genügend Informationen, damit Kunden sicher sein können, dass ihre Anfrage ordnungsgemäß bearbeitet wurde.
quelle
Ich persönlich kehre immer nur zurück
200 OK
.Um Ihre Frage zu zitieren
Warum zusätzliche Bandbreite hinzufügen (die möglicherweise bezahlt werden muss), um dem Kunden mitzuteilen, was er bereits weiß?
quelle
200
/ finden Sie unter stackoverflow.com/a/827045/290182204 No Content
, um Verwirrung bei jQuery und dergleichen zu vermeiden.@iswinky Ich würde die Nutzdaten immer zurücksenden, sowohl bei POST als auch bei PUT.
Bei einem POST können Sie die Entität mit einer internen ID oder einer UUID erstellen. Daher ist es sinnvoll, die Nutzlast zurückzusenden.
In ähnlicher Weise könnten Sie im Fall von PUT einige Felder des Benutzers ignorieren (z. B. unveränderliche Werte), oder im Fall eines PATCHs könnten die Daten auch von anderen Benutzern geändert worden sein.
Es ist immer eine gute Idee, die Daten so zurückzusenden, wie sie beibehalten wurden, und sie schaden definitiv nicht. Wenn der Anrufer diese zurückgegebenen Daten nicht benötigt, verarbeitet er sie nicht, sondern verwendet nur den statusCode. Andernfalls können sie diese Daten verwenden, um die Benutzeroberfläche zu aktualisieren.
Nur im Falle eines DELETE würde ich die Nutzdaten nicht zurücksenden und entweder eine 200 mit einem Antwortinhalt oder eine 204 ohne Antwortinhalt ausführen.
Edit: Dank einiger Kommentare von unten schreibe ich meine Antwort um. Ich stehe nach wie vor zu der Art und Weise, wie ich meine APIs entwerfe und Antworten zurücksende, aber ich halte es für sinnvoll, einige meiner Entwurfsüberlegungen zu qualifizieren.
a) Wenn ich sage, dass die Nutzdaten zurückgesendet werden sollen, wollte ich eigentlich sagen, dass die Daten der Ressource zurückgesendet werden sollen, nicht die Nutzdaten, die in der Anforderung enthalten sind. Beispiel: Wenn Sie eine Nutzlast zum Erstellen senden, kann ich im Backend andere Entitäten wie UUID und (möglicherweise) Zeitstempel und sogar einige (Diagramm-) Verbindungen erstellen. Ich würde das alles in der Antwort zurückschicken (nicht nur die Nutzlast der Anfrage wie sie ist - was sinnlos ist).
b) Ich würde keine Antworten zurücksenden, wenn die Nutzlast sehr groß ist. Ich habe dies in den Kommentaren besprochen, aber ich möchte darauf hinweisen, dass ich mein Bestes geben würde, um meine APIs oder Ressourcen so zu gestalten, dass keine sehr großen Nutzlasten erforderlich sind. Ich würde versuchen, die Ressourcen in kleinere und verwaltbare Einheiten aufzuteilen, sodass jede Ressource durch 15-20 JSON-Attribute definiert wird und nicht durch größere.
In dem Fall, dass das Objekt sehr groß ist oder das übergeordnete Objekt aktualisiert wird, würde ich die verschachtelten Strukturen als hrefs zurücksenden.
Unterm Strich würde ich auf jeden Fall versuchen, die Daten zurückzusenden, die für den Verbraucher / die Benutzeroberfläche sinnvoll sind, um sie sofort zu verarbeiten, und zwar mit einer atomaren API-Aktion, anstatt 2-5 weitere APIs abrufen zu müssen, nur um die Benutzeroberfläche zu aktualisieren Erstellung / Aktualisierung der Daten.
Server-zu-Server-APIs denken möglicherweise anders darüber. Ich konzentriere mich auf APIs, die eine Benutzererfahrung fahren.
quelle
Wenn Sie auf die Link- RFC-Standards verweisen , sollten Sie den Status 201 (erstellt) zurückgeben, wenn Sie die Anforderungsressource erfolgreich mit "Posten" speichern. In den meisten Anwendungen wird die ID der Ressource vom Server selbst generiert. Daher empfiehlt es sich, die ID der erstellten Ressource zurückzugeben. Die Rücksendung des gesamten Objekts ist der Aufwand für die Post-Anfrage. In der Regel wird der URL-Speicherort der neu erstellten Ressource zurückgegeben.
Sie können beispielsweise auf das folgende Beispiel verweisen, in dem das Mitarbeiterobjekt in der Datenbank gespeichert und die URL des neu erstellten Ressourcenobjekts als Antwort zurückgegeben wird.
Dieser Rest-Endpunkt gibt die Antwort wie folgt zurück:
Status 201 - ERSTELLT
Header Location → http: // localhost: 8080 / employee / 1
quelle
Ich würde eine Nutzlast im Rückgabetext von einem HTTP-Parameter abhängig machen.
In den meisten Fällen ist es am besten, Inhalte an den API-Konsumenten zurückzugeben, um unnötige Roundtrips zu vermeiden (einer der Gründe, warum GraphQL existiert).
In der Tat versuche ich, diese Richtlinie zu beachten, wenn unsere Anwendungen datenintensiver und verteilter werden:
Meine Richtlinie :
Immer wenn ein Anwendungsfall ein GET unmittelbar nach einem POST oder PUT erfordert, ist es möglicherweise am besten, einfach etwas in der POST / PUT-Antwort zurückzugeben.
Wie dies geschieht und welche Art von Inhalten aus einem PUT oder POST zurückgegeben werden sollen, ist anwendungsspezifisch. Jetzt wäre es interessant, wenn die Anwendung den Typ des "Inhalts" im Antworttext parametrisieren könnte (möchten wir nur den Ort des neuen Objekts oder einige der Felder oder das gesamte Objekt usw.).
Eine Anwendung kann eine Reihe von Parametern definieren, die ein POST / PUT empfangen kann, um die Art des "Inhalts" zu steuern, der im Antworttext zurückgegeben werden soll. Oder es könnte eine Art GraphQL-Abfrage als Parameter codieren (ich kann dies als nützlich erachten, aber auch als Alptraum für die Wartung.)
So oder so scheint es mir, dass:
Also, 1) mach es, aber 2) halte es einfach.
Eine andere Option, die ich gesehen habe, ist das Erstellen alternativer Endpunkte (z. B. / customers für POST / PUT, die nichts im Hauptteil und / customer_with_details für POST / PUT an / customers zurückgeben, aber etwas im Antworthauptteil).
Ich würde diesen Ansatz jedoch vermeiden. Was passiert, wenn Sie berechtigterweise verschiedene Arten von Inhalten zurückgeben müssen? Ein Endpunkt pro Inhaltstyp? Nicht skalierbar oder wartbar.
quelle