Ist es per REST in Ordnung, Inhalte nach dem POST zurückzugeben?

87

Ich verwende RESTlet und habe eine Ressource erstellt. Ich behandle POST durch Überschreiben der acceptRepresentationMethode.

Der Client sollte mir einige Daten senden, dann speichere ich sie in der Datenbank, setze die Antwort auf 201 (SUCCESS_CREATED) und muss einige Daten an den Client zurückgeben, aber der Rückgabetyp acceptRepresentationist void.

In meinem Fall muss ich einen Bezeichner zurückgeben, damit der Client auf diese Ressource zugreifen kann.

Wenn ich beispielsweise eine Ressource mit URL hatte /resourceund der Client eine POST-Anfrage sendet, füge ich eine neue Zeile in die Datenbank ein und deren Adresse sollte lauten /resource/{id}. Ich muss senden {id}.

Mache ich etwas falsch? Können nach den REST-Prinzipien nach dem POST etwas zurückgegeben werden? Wenn ja, wie kann ich das machen und wenn nein, wie gehe ich mit dieser Situation um?

Del-Boy
quelle
In Thoms Antwort erfahren Sie, wie Sie den Antworttext in acceptRepresentation () festlegen.
Avi Flax

Antworten:

95

REST sagt nur, dass Sie sich an die einheitliche Schnittstelle anpassen sollten. Mit anderen Worten, es heißt, Sie sollten das tun, was POST gemäß der HTTP-Spezifikation tun soll . Hier ist das Zitat aus dieser Spezifikation, das relevant ist:

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

Wie Sie sehen können, haben Sie zwei Stellen, an denen Sie dem Client angeben können, wo sich die neu erstellte Ressource befindet. Der Standortheader sollte eine URL enthalten, die auf die neue Ressource verweist, und Sie können auch eine Entität mit den Details zurückgeben.

Ich bin nicht sicher, was der Unterschied zwischen dem Überschreiben von acceptRepresentation () und dem Überschreiben von post () ist, aber dieses Beispiel zeigt, wie eine Antwort von einem POST zurückgegeben wird.

Darrel Miller
quelle
2
@ del-boy: In Thoms Antwort erfahren Sie, wie Sie den Antworttext in acceptRepresentation () festlegen.
Avi Flax
1
Das HTTP-Spezifikationszitat verbietet keine Antwort. Wenn Sie in Abschnitt 6 nachsehen, ist dies klar: Es ist zulässig: Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or response status code. An entity consists of entity-header fields and an entity-body, although some responses will only include the entity-headers.
MikeF
@MikeF Es war nicht meine Absicht zu schließen, dass ein Antwortkörper nicht erlaubt war. Der Teil der Spezifikation, den ich zitiert habe, sagt ausdrücklich "und enthält eine Entität". Ich hätte in meinem Text klarer sein sollen.
Darrel Miller
16

Ich würde darauf verzichten, irgendetwas im Text der Antwort zu senden. Setzen Sie einfach Location: auf die (vollständige) URL der neu erstellten Ressource.

Ihre Beschreibung legt nahe, dass dies genau die Semantik ist, die Sie:

  1. POST eine Sache, um es zu erstellen
  2. Antworten Sie mit genug, um zwei Dinge zu wissen:
    1. Dass die Schöpfung geschah (die 201)
    2. Wo finde ich das Neue? (Location Header)

Alles andere ist überflüssig.

cdent
quelle
Nicht, dass Wikipedia immer eine gute Quelle ist, aber es wird auch behauptet, "[...] um Informationen über den Standort einer neu erstellten Ressource bereitzustellen. Unter diesen Umständen sollte der Standortheader mit einem HTTP-Statuscode von 201 oder 202 gesendet werden . "
Arjan
1
POST kann eine Logik ausführen, die eine oder mehrere Ressourcen erstellt. Das Ergebnis der Verarbeitung kann vom Kunden benötigt werden. Wenn Sie es in der Antwort zurückgeben, müssen Sie keinen oder mehrere GET-Aufrufe an die API senden. Die mit der POST-Methode erstellten / geänderten Daten sind für den Client möglicherweise nicht (und oft auch nicht) überflüssig.
Paulo Merson
10

Zwei verschiedene Fragen:

Unterstützt das REST-Anwendungsmuster die Rückgabe von Daten in einem POST?

Ich glaube nicht, dass REST dies ausdrücklich verbietet, aber die bevorzugte Behandlung ist in Darrels Antwort dargelegt.

Ermöglicht das RESTlet-Framework die Rückgabe von Daten in einem POST?

Ja, obwohl es void zurückgibt, haben Sie in einer Klasse, die Resource erweitert, über die Methode getResponse () vollen Zugriff auf das Objekt Object Response. Sie können also getResponse (). SetEntity () mit beliebigen Daten aufrufen.

Thom
quelle
6

Geben Sie es in dem gewünschten Format aus. Das könnte sein:

<success>
    <id>5483</id>
</success>

Oder:

{ "type": "success", "id": 5483 }

Es hängt davon ab, was Sie normalerweise tun. Wenn sie die Daten nicht erwarten, sollten sie sie einfach ignorieren, aber jeder Client, der sie richtig verarbeiten möchte, sollte dies können.

Samir Talwar
quelle
Ok, ich habe zwei mögliche Formate (HTML und XML). Ich weiß, wie ich mit dem Typ des angeforderten Formats umgehen soll, aber ich weiß nicht, wie ich der Antwort Daten hinzufügen soll. Repräsentationsmethode gibt Repräsentation zurück, also gebe ich einfach zurück, was immer ich will, aber acceptRepresentation ist eine ungültige Methode, daher kann ich keine Daten zurückgeben ...
del-boy
1

Wenn Sie antworten 201 Erstellt mit einem Entitätskörper anstelle einer Standortumleitung, ist es eine gute Idee, einen Content-Location-Header einzufügen, der auf die Ressource verweist, die in der Antwort dargestellt wird.

Dies vermeidet mögliche Verwirrung - bei der ein Client (zu Recht) annehmen könnte, dass die Antwortentität tatsächlich einen neuen Status des "Erstellers" und nicht der erstellten Ressource darstellt.

> POST /collection
> ..new item..

< 201 Created
< Location: /collection/1354
< Content-Location: /collection/1354
< <div class="item">This is the new item that was created</div>
Mike
quelle
3
Ich denke, Content-Location dient einem anderen Zweck. Die HTTP-Spezifikation besagt, dass Content-Location für POST und PUT nicht definiert ist. Der Location-Header wird bei einem 201-Create verwendet. Das Zurückgeben eines Standorts führt nicht automatisch eine Umleitung durch. Dazu benötigen Sie einen 3XX-Antwortcode.
Darrel Miller
1
Der Standortheader wird (in einer 201-Antwort) verwendet, um anzugeben, wo sich eine erstellte Ressource befindet. Es ist nicht relevant für den Entitätskörper der Antwort, die es begleitet. Mein Punkt war, dass - wenn Sie die erstellte Ressource in die 201-Antwort selbst aufnehmen möchten (anstatt den Client an einen anderen URI weiterzuleiten / umzuleiten), ein Content-Location-Header eine gute Idee wäre. Dies ist wahrscheinlich ein bisschen "Biegen der Regeln", aber es ist effizienter, als einen weiteren Anforderungs- / Antwortzyklus zu benötigen, um den Status der neuen Ressource an den Client zu senden.
Mike
Das macht Sinn. Ich habe den Content-Location-Header noch nie verwendet.
Darrel Miller
Wenn der Client ein Mensch mit einem Browser ist, macht es keinen Sinn, 201 mit dem Standortheader zurückzugeben. Der Benutzer weiß nicht, was er damit machen soll. Wenn der Client ein Roboter ist, kann er so programmiert werden, dass er weiß, wie er damit umgeht - wie ein Follow-up-GET am Standort.
Unbestreitbarer
3
@irreputable: Ich glaube, dass REST für das Entwerfen von APIs gedacht war, wobei A nicht für einen Benutzeragenten steht, der nach HTML zum Rendern sucht.
Hermes