it-swarm.com.de

RESTful API. Sollte ich das erstellte / aktualisierte Objekt zurückgeben?

Ich entwerfe einen RESTful-Webdienst mit WebApi und habe mich gefragt, welche HTTP-Antworten und Antwortkörper beim Aktualisieren/Erstellen von Objekten zurückgegeben werden sollen.

Zum Beispiel kann ich die Methode POST] verwenden, um JSON an den Webdienst zu senden und dann ein Objekt zu erstellen. Es wird empfohlen, den HTTP-Status auf "erstellt" (201) oder "ok" (200) zu setzen ) und einfach eine Nachricht wie "Neuer Mitarbeiter hinzugefügt" zurückgeben oder das ursprünglich gesendete Objekt zurückgeben?

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? In Anbetracht der Tatsache, dass der Benutzer ohnehin weiß, welches Objekt er 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 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 mit nur Statuscode:

HTTP/1.1 204 No Content
Content-Length: 39
Date: Mon, 28 Mar 2016 14:32:39 GMT
44
iswinky

Wie bei den meisten Dingen kommt es darauf an. Ihr Kompromiss ist die Benutzerfreundlichkeit gegenüber der Netzwerkgröße. Es kann für Clients sehr hilfreich sein, die erstellte Ressource anzuzeigen. Es kann Felder enthalten, die vom Server ausgefüllt werden, z. B. die Zeit der letzten Erstellung. Da Sie anscheinend id anstelle von hateoas einschließen, möchten Clients wahrscheinlich die ID für die Ressource sehen, die sie gerade POSTed haben.

Wenn Sie die erstellte Ressource nicht einschließen, erstellen Sie bitte keine beliebige Nachricht. Die Felder 2xx und Standort sind genug Informationen, damit Kunden sicher sein können, dass ihre Anfrage ordnungsgemäß bearbeitet wurde.

38
Eric Stein

Persönlich gebe ich immer nur 200 OK Zurück.

Um Ihre Frage zu zitieren

In Anbetracht der Tatsache, dass der Benutzer ohnehin weiß, welches Objekt er erstellen/aktualisieren möchte.

Warum zusätzliche Bandbreite hinzufügen (die möglicherweise bezahlt werden muss), um dem Kunden mitzuteilen, was er bereits weiß?

Wenn Sie auf den Link RFC-Standards verweisen, sollten Sie den Status 201 (erstellt) zurückgeben, wenn Sie die Anforderungsressource erfolgreich mit Post speichern. In den meisten Anwendungen wird die ID der Ressource vom Server selbst generiert. Es wird daher empfohlen, die ID der erstellten Ressource zurückzugeben. Das Zurückgeben des gesamten Objekts ist der Overhead für die Post-Anfrage. Die ideale Vorgehensweise besteht darin, den URL-Speicherort der neu erstellten Ressource zurückzugeben.

Sie können sich beispielsweise auf das folgende Beispiel beziehen, in dem das Mitarbeiterobjekt in der Datenbank gespeichert und die URL des neu erstellten Ressourcenobjekts als Antwort zurückgegeben wird.

@RequestMapping(path = "/employees", method = RequestMethod.POST)
public ResponseEntity<Object> saveEmployee(@RequestBody Employee employee) {
        int id = employeeService.saveEmployee(employee);
        URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(id).toUri();
        return ResponseEntity.created(uri).build();
}

Dieser Ruheendpunkt gibt die Antwort zurück als:

Status 201 - ERSTELLT

Header-Speicherort → http: // localhost: 8080/employee/1

10

@iswinky Ich würde immer die Nutzdaten zurücksenden, wenn sowohl POST als auch PUT.

Im Fall von POST können Sie die Entität mit einer internen ID oder einer UUID erstellen. Daher ist es sinnvoll, die Nutzdaten zurückzusenden.

In ähnlicher Weise können Sie im Fall von PUT einige Felder des Benutzers ignorieren (z. B. unveränderliche Werte), oder im Fall eines PATCH wurden die Daten möglicherweise auch von anderen Benutzern geändert.

Das Zurücksenden der Daten, wie sie beibehalten wurden, ist immer eine gute Idee und schadet 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 LÖSCHENS würde ich die Nutzdaten nicht zurücksenden und entweder eine 200 mit einem Antwortinhalt oder eine 204 ohne Antwortinhalt ausführen.

Bearbeiten: Dank einiger Kommentare von unten formuliere ich meine Antwort neu. Ich stehe immer noch zu der Art und Weise, wie ich meine APIs entwerfe und Antworten zurücksende, aber ich denke, es ist sinnvoll, einige meiner Entwurfsgedanken 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, nicht die gleiche Nutzlast, die in der Anforderung enthalten war. Beispiel: Wenn Sie eine Nutzlast zum Erstellen senden, kann ich im Backend andere Entitäten wie UUID und (möglicherweise) Zeitstempel und einige (Grafik-) Verbindungen sogar erstellen. Ich würde dies alles in der Antwort zurücksenden (nicht nur die Anforderungsnutzlast 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 sie keine sehr großen Nutzdaten haben müssen. Ich würde versuchen, die Ressourcen in kleinere und verwaltbare Entitäten aufzuteilen, sodass jede Ressource durch 15-20 JSON-Attribute definiert wird und nicht größer.

Für den Fall, dass das Objekt sehr groß ist oder das übergeordnete Objekt aktualisiert wird, würde ich die verschachtelten Strukturen als hrefs zurücksenden.

Fazit ist, dass ich definitiv versuchen würde, die Daten zurückzusenden, die für den Verbraucher/die Benutzeroberfläche sinnvoll sind, um sie sofort zu verarbeiten und mit einer atomaren API-Aktion fertig zu werden, anstatt 2-5 weitere APIs abrufen zu müssen, nur um die Benutzeroberfläche nach dem zu aktualisieren Erstellung/Aktualisierung der Daten.

Server-zu-Server-APIs denken möglicherweise anders darüber nach. Ich konzentriere mich auf APIs, die eine Benutzererfahrung fördern.

10
ksprashu

Ich würde eine Nutzlast im Rückgabekörper 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 es einen Anwendungsfall gibt, der ein GET unmittelbar nach einem POST oder PUT) erfordert, ist es in diesem Fall möglicherweise am besten, einfach etwas in der POST/PUT-Antwort zurückzugeben.

Wie dies gemacht wird und welche Art von Inhalt aus einem PUT oder POST zurückgegeben werden soll, ist anwendungsspezifisch. Nun wäre es interessant, wenn die Anwendung den Typ des "Inhalts" im Antworttext parametrisieren könnte (wollen wir nur die Position des neuen Objekts oder einiger Felder oder des gesamten Objekts usw.)?

Eine Anwendung könnte 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 sehen, dass dies nützlich ist, aber auch zu einem Wartungs-Albtraum wird.)

Wie auch immer, es scheint mir, dass:

  1. Es ist in Ordnung (und höchstwahrscheinlich wünschenswert), etwas in einem POST/PUT-Antworttext zurückzugeben.
  2. Wie dies gemacht wird, ist anwendungsspezifisch und fast unmöglich zu verallgemeinern.
  3. Sie möchten standardmäßig keinen großen "Kontext" zurückgeben (Verkehrsgeräusche, die den gesamten Grund für die Abkehr von POST-gefolgt von GETs zunichte machen).

Also, 1) mach es, aber 2) halte es einfach.

Eine andere Option, die ich gesehen habe, sind Leute, die alternative Endpunkte erstellen (z. B./customers für POST/PUT, die nichts im Text und/customer_with_details für POST/PUT an/customers zurückgeben, aber etwas im Antworttext zurückgeben).

Ich würde diesen Ansatz jedoch vermeiden. Was passiert, wenn Sie zu Recht unterschiedliche Arten von Inhalten zurückgeben müssen? Ein Endpunkt pro Inhaltstyp? Nicht skalierbar oder wartbar.

0
luis.espinal