Bei der Ausgabe einer HTTP-DELETE-Anforderung sollte der Anforderungs-URI die zu löschende Ressource vollständig identifizieren. Ist es jedoch zulässig, zusätzliche Metadaten als Teil des Entitätstextes der Anforderung hinzuzufügen?
Bei der Ausgabe einer HTTP-DELETE-Anforderung sollte der Anforderungs-URI die zu löschende Ressource vollständig identifizieren. Ist es jedoch zulässig, zusätzliche Metadaten als Teil des Entitätstextes der Anforderung hinzuzufügen?
Antworten:
Die Spezifikation verbietet oder entmutigt sie nicht ausdrücklich, daher würde ich eher sagen, dass sie zulässig ist.
Microsoft sieht das genauso (ich kann im Publikum ein Murmeln hören), heißt es im MSDN-Artikel über die DELETE-Methode von ADO.NET Data Services Framework :
Wenn eine DELETE-Anforderung einen Entitätskörper enthält, wird der Körper ignoriert [...]
Zusätzlich ist hier, was RFC2616 (HTTP 1.1) zu Anfragen zu sagen hat:
Content-Length
oder eines Transfer-Encoding
Headers signalisiert (Abschnitt 4.3).Für Antworten wurde Folgendes definiert:
Das neueste Update der HTTP 1.1-Spezifikation ( RFC 7231 ) erlaubt explizit einen Entitätstext in einer DELETE-Anforderung:
Eine Nutzlast innerhalb einer DELETE-Anforderungsnachricht hat keine definierte Semantik. Das Senden eines Nutzdatenkörpers bei einer DELETE-Anforderung kann dazu führen, dass einige vorhandene Implementierungen die Anforderung ablehnen.
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
also eine Abwärtskompatibilitätswarnung angezeigt, die darauf hinweist, dass der nächste Standard lautet: 'yep! DELETE
kann einen Körper haben`.
A payload within a DELETE request message has no defined semantics
. Also ist der Körper erlaubt.
Einige Versionen von Tomcat und Jetty scheinen einen Entity-Body zu ignorieren, wenn er vorhanden ist. Was ein Ärgernis sein kann, wenn Sie es erhalten möchten.
Ein Grund für die Verwendung des Body in einer Löschanforderung ist die optimistische Parallelitätskontrolle.
Sie lesen Version 1 eines Datensatzes.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Ihr Kollege liest Version 1 des Datensatzes.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Ihr Kollege ändert den Datensatz und aktualisiert die Datenbank, wodurch die Version auf 2 aktualisiert wird:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
Sie versuchen, den Datensatz zu löschen:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
Sie sollten eine optimistische Sperrausnahme erhalten. Lesen Sie den Datensatz erneut, stellen Sie sicher, dass er wichtig ist, und löschen Sie ihn möglicherweise nicht.
Ein weiterer Grund für die Verwendung besteht darin, mehrere Datensätze gleichzeitig zu löschen (z. B. ein Raster mit Kontrollkästchen für die Zeilenauswahl).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Beachten Sie, dass jede Nachricht eine eigene Version hat. Vielleicht können Sie mehrere Versionen mit mehreren Headern angeben, aber von George ist dies einfacher und viel bequemer.
Dies funktioniert in Tomcat (7.0.52) und Spring MVC (4.05), möglicherweise auch in früheren Versionen:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
If-Unmodified-Since
oder dafür Etag
sind sie da).
Es scheint mir, dass RFC 2616 dies nicht spezifiziert.
Aus Abschnitt 4.3:
Das Vorhandensein eines Nachrichtentexts in einer Anforderung wird durch die Aufnahme eines Headerfelds für Inhaltslänge oder Übertragungscodierung in die Nachrichtenkopfzeilen der Anforderung signalisiert. Ein Nachrichtentext DARF NICHT in eine Anforderung aufgenommen werden, wenn die Angabe der Anforderungsmethode (Abschnitt 5.1.1) das Senden eines Entitätstexts in Anforderungen nicht zulässt. Ein Server sollte bei jeder Anfrage einen Nachrichtentext lesen und weiterleiten. Wenn die Anforderungsmethode keine definierte Semantik für einen Entitätskörper enthält, MUSS der Nachrichtentext bei der Verarbeitung der Anforderung ignoriert werden.
Und Abschnitt 9.7:
Die DELETE-Methode fordert den Ursprungsserver auf, die durch den Request-URI identifizierte Ressource zu löschen. Diese Methode kann durch menschliches Eingreifen (oder auf andere Weise) auf dem Ursprungsserver überschrieben werden. Dem Client kann nicht garantiert werden, dass der Vorgang ausgeführt wurde, selbst wenn der vom Ursprungsserver zurückgegebene Statuscode anzeigt, dass die Aktion erfolgreich abgeschlossen wurde. Der Server sollte jedoch KEINEN Erfolg anzeigen, es sei denn, er beabsichtigt zum Zeitpunkt der Antwort, die Ressource zu löschen oder an einen unzugänglichen Ort zu verschieben.
Eine erfolgreiche Antwort sollte 200 (OK) sein, wenn die Antwort eine Entität enthält, die den Status beschreibt, 202 (Akzeptiert), wenn die Aktion noch nicht ausgeführt wurde, oder 204 (Kein Inhalt), wenn die Aktion ausgeführt wurde, die Antwort jedoch nicht enthält eine Entität.
Wenn die Anforderung einen Cache durchläuft und der Anforderungs-URI eine oder mehrere aktuell zwischengespeicherte Entitäten identifiziert, MÜSSEN diese Einträge als veraltet behandelt werden. Antworten auf diese Methode können nicht zwischengespeichert werden. C.
Es ist also nicht explizit erlaubt oder nicht erlaubt, und es besteht die Möglichkeit, dass ein Proxy auf dem Weg den Nachrichtentext entfernt (obwohl er ihn lesen und weiterleiten sollte).
Nur ein Kopf hoch, wenn Sie einen Text in Ihrer DELETE-Anfrage angeben und einen Google Cloud HTTPS-Load-Balancer verwenden, wird Ihre Anfrage mit einem 400-Fehler abgelehnt. Ich schlug meinen Kopf gegen eine Wand und stellte fest, dass Google aus irgendeinem Grund eine DELETE-Anfrage mit einem Körper für eine fehlerhafte Anfrage hält.
for whatever reason
- weil die Spezifikation so sagt: P
DELETE
Letzteres ist die Verwendung eines Nachrichtentexts .
Es scheint, dass ElasticSearch dies verwendet: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
Was bedeutet, dass Netty dies unterstützt.
Wie in den Kommentaren erwähnt, ist dies möglicherweise nicht mehr der Fall
Roy Fielding auf der HTTP-Mailingliste stellt klar, dass auf der http-Mailingliste https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html :
Es ist absolut verboten, dass GET / DELETE-Körper irgendwelche Auswirkungen auf die Verarbeitung oder Interpretation der Anfrage haben
Dies bedeutet, dass der Body das Verhalten des Servers nicht ändern darf. Dann fügt er hinzu:
abgesehen von der Notwendigkeit, die empfangenen Bytes zu lesen und zu verwerfen, um den Nachrichtenrahmen aufrechtzuerhalten.
Und schließlich der Grund, den Körper nicht zu verbieten:
Der einzige Grund, warum wir das Senden eines Körpers nicht verboten haben, ist, dass dies zu verzögerten Implementierungen führen würde, vorausgesetzt, dass kein Körper gesendet wird.
Während Clients den Payload-Body senden können, sollten Server ihn löschen und APIs sollten bei diesen Anforderungen keine Semantik für den Payload-Body definieren.
Dies ist nicht definiert .
Eine Nutzlast innerhalb einer DELETE-Anforderungsnachricht hat keine definierte Semantik. Das Senden eines Nutzdatenkörpers bei einer DELETE-Anforderung kann dazu führen, dass einige vorhandene Implementierungen die Anforderung ablehnen.
https://tools.ietf.org/html/rfc7231#page-29
Die Verwendung von DELETE mit einem Body ist riskant ... Ich bevorzuge diesen Ansatz für Listenoperationen gegenüber REST:
Regelmäßiger Betrieb
GET / objects / Ruft alle Objekte ab
GET / object / ID Ruft ein Objekt mit der angegebenen ID ab
POST / Objekte Fügt ein neues Objekt hinzu
PUT / Objekt / ID Fügt ein Objekt mit der angegebenen ID hinzu und aktualisiert ein Objekt
LÖSCHEN / Objekt / ID Löscht das Objekt mit der angegebenen ID
Alle benutzerdefinierten Aktionen sind POST
POST / objects / addList Fügt eine Liste oder ein Array von Objekten hinzu, die im Hauptteil enthalten sind
POST / objects / deleteList Löscht eine Liste der im Hauptteil enthaltenen Objekte
POST / objects / customQuery Erstellt eine Liste basierend auf einer benutzerdefinierten Abfrage im Hauptteil
Wenn ein Client Ihre erweiterten Vorgänge nicht unterstützt, kann er normal arbeiten.
POST
ist keine gute RESTy-Methode zum Erstellen neuer Ressourcen, da die Semantik von POST-Antworten unklar ist, insbesondere im Zusammenhang mit Standortheadern. Sie lassen HTTP im Wesentlichen hinter sich und stapeln RPC oben drauf. Der richtige "HTTP / REST-Weg" besteht darin, Ressourcen mit PUT
dem If-None-Match: *
Header zu erstellen (oder geeignete HTTP-Methoden anzugeben, siehe MKCOL
usw.).
Ich glaube nicht, dass eine gute Antwort darauf veröffentlicht wurde, obwohl es viele großartige Kommentare zu vorhandenen Antworten gab. Ich werde den Kern dieser Kommentare in eine neue Antwort umwandeln:
Dieser Absatz aus RFC7231 wurde einige Male zitiert, was es zusammenfasst.
Eine Nutzlast innerhalb einer DELETE-Anforderungsnachricht hat keine definierte Semantik. Das Senden eines Nutzdatenkörpers bei einer DELETE-Anforderung kann dazu führen, dass einige vorhandene Implementierungen die Anforderung ablehnen.
Was ich bei den anderen Antworten vermisst habe, war die Implikation. Ja, es ist erlaubt, einen Text in DELETE
Anfragen aufzunehmen, aber es ist semantisch bedeutungslos. Dies bedeutet wirklich, dass das Ausgeben einer DELETE
Anforderung mit einem Anforderungshauptteil semantisch dem Nichteinschließen eines Anforderungshauptteils entspricht.
Das Einschließen eines Anforderungshauptteils sollte keine Auswirkungen auf die Anforderung haben, daher macht es keinen Sinn, sie einzuschließen.
tl; dr: Technisch gesehen ist eine DELETE
Anfrage mit einem Anfragetext zulässig, dies ist jedoch niemals sinnvoll.
Falls jemand auf dieses Problem stößt, wird es nicht allgemein unterstützt.
Ich teste derzeit mit Sahi Pro und es ist sehr offensichtlich, dass ein http DELETE-Aufruf alle bereitgestellten Körperdaten entfernt (eine große Liste von IDs, die gemäß dem Endpunktdesign in großen Mengen gelöscht werden sollen).
Ich war mehrere Male mit ihnen in Kontakt und habe drei separate Pakete mit Skripten, Bildern und Protokollen gesendet, damit sie sie überprüfen können, und sie haben dies immer noch nicht bestätigt. Ein fehlgeschlagener Patch und verpasste Telefonkonferenzen durch ihren Support später, und ich habe immer noch keine solide Antwort erhalten.
Ich bin mir sicher, dass Sahi dies nicht unterstützt, und ich würde mir vorstellen, dass viele andere Tools der Suite folgen.
Möglicherweise hilft Ihnen die unten stehende GitHUb-URL, die Antwort zu erhalten. Tatsächlich lehnt Application Server wie Tomcat, Weblogic den Aufruf von HTTP.DELETE mit Anforderungsnutzdaten ab. Unter Berücksichtigung all dieser Dinge habe ich ein Beispiel in Github hinzugefügt. Bitte schauen Sie sich das an
Ich konnte die DELETE-Operation mit einem Anforderungshauptteil implementieren. Ich habe AWS Lambda und AWS API Gateway verwendet und die Sprache Go verwendet.