Löschen einer Ressource mit http DELETE

122

Wenn das folgende DELETE-Verb in HTTP idempotent ist, was sollte dann beim zweiten (oder dritten oder vierten usw.) geschehen, wenn ich die folgende Anfrage stelle?

DELETE /person/123

Beim ersten Mal wird die Ressource gelöscht und ich gebe eine 204 zurück (erfolgreich, kein Inhalt). Sollte ich bei nachfolgenden Anrufen einen 204 oder einen 404 (nicht gefunden) zurückgeben?

Craig Wilson
quelle

Antworten:

152

Da HTTP-Anforderungen in einem zustandslosen System unabhängig sein sollten, sollten die Ergebnisse einer Anforderung nicht von einer vorherigen Anforderung abhängig sein. Überlegen Sie, was passieren soll, wenn zwei Benutzer gleichzeitig ein DELETE für dieselbe Ressource ausführen. Es ist sinnvoll, dass die zweite Anforderung eine 404 erhält. Dasselbe sollte zutreffen, wenn ein Benutzer zwei Anforderungen stellt.

Ich vermute, dass es für Sie nicht idempotent ist, wenn DELETE zwei verschiedene Antworten zurückgibt. Ich finde es nützlich, sich idempotente Anfragen so vorzustellen, dass das System im selben Zustand bleibt und nicht unbedingt dieselbe Antwort hat. Unabhängig davon, ob Sie eine vorhandene Ressource LÖSCHEN oder versuchen, eine nicht vorhandene Ressource zu LÖSCHEN, ist der Serverressourcenstatus derselbe.

Darrel Miller
quelle
4
Danke dir. Das macht so viel Sinn. Ich dachte tatsächlich, idempotent würde dieselbe Antwort zurückgeben.
Craig Wilson
4
@Craig Vorsicht! Im Kochbuch widerspricht Subbu völlig dem, was ich gerade gesagt habe. Er sagt, Idempotenz bedeutet, dass sie die gleiche Antwort zurückgeben sollte. Zum Glück wird Subbu beim RESTFest sein, also werde ich dort mit ihm klären.
Darrel Miller
57
Wenn Sie etwas LÖSCHEN, das nicht existiert, sollten Sie einfach eine 204 zurückgeben (auch wenn die Ressource nie existiert hat). Der Client wollte, dass die Ressource weg ist und sie weg ist. Wenn Sie einen 404 zurückgeben, wird die interne Verarbeitung verfügbar gemacht, die für den Client unwichtig ist und zu einer unnötigen Fehlerbedingung führt.
Brian
9
@DarrelMiller Ich denke, das Schlüsselkonzept hier ist, dass Sie DELETE nicht verwenden sollten, um zu überprüfen, ob eine Ressource vorhanden ist. Sie würden dafür zuerst GET verwenden. Wenn die Antwort dann 200 ist, führen Sie ein LÖSCHEN aus. sonst mach dir nicht mal die Mühe das zu tun. Daher halte ich es für sinnvoll, bei DELETE immer einen 204 zurückzugeben.
manei_cc
10
@Brian Der RFC sagt, es soll sich so verhalten rm. rmGibt einen Fehler zurück, wenn er nicht vorhanden ist. tools.ietf.org/html/rfc7231#section-4.3.5
Dax Fohl
32

Das RESTful-Webdienst-Kochbuch ist hierfür eine hervorragende Ressource. Zufällig zeigt die Google-Vorschau die Seite über LÖSCHEN (Seite 11):

Die DELETE-Methode ist idempotent. Dies bedeutet, dass der Server den Antwortcode 200 (OK) zurückgeben muss, auch wenn der Server die Ressource in einer vorherigen Anforderung gelöscht hat. In der Praxis erfordert die Implementierung von DELETE als idempotente Operation jedoch, dass der Server alle gelöschten Ressourcen im Auge behält. Andernfalls kann ein 404 (nicht gefunden) zurückgegeben werden.

yves amsellem
quelle
Ja, das sieht nach einer großartigen Ressource aus. Der Abschnitt LÖSCHEN wird für mich jedoch nicht aufgerufen (es ist Seite 23 und die Vorschau hat diese redigiert). Hast du dieses Buch gelesen? Kennen Sie zufällig die Antwort auf meine Frage?
Craig Wilson
Dieses Buch ist ein Muss für die Erstellung von REST (es spricht insbesondere nicht in einer Sprache).
Yves Amsellem
7
@Craig Wenn Sie das Kochbuch lesen, heißt es, dass Sie 200 OK zurückgeben sollten, auch wenn Sie es bereits gelöscht haben. In der Praxis müsste der Server jedoch alle gelöschten Ressourcen nachverfolgen. Daher KÖNNEN Sie 404 verwenden. Aus Sicherheitsgründen müssen Sie möglicherweise immer 404 zurückgeben.
Darrel Miller
+1 Zweitens und empfehlen Sie das Buch für die Gestaltung von RESTful-Services.
Paul DelRe
18
Nun, das Buch ist falsch. Idempotenz bedeutet nicht, dass der Statuscode der gleiche ist. Relevant ist der Endzustand des Servers.
Julian Reschke
13

Ich stimme dem zu, was die aktuell gewählte Antwort gesagt hat, dass die 2. (und 3., 4., ...) LÖSCHEN eine 404 bekommen sollte . Und ich habe festgestellt, dass die Antwort 143 Stimmen hat, aber auch einen entgegengesetzten Kommentar, der 54 Stimmen hat, so dass die Community in zwei Lager im Verhältnis 3: 1 aufgeteilt ist. Hier finden Sie weitere Informationen zur Beilegung dieser langjährigen Debatte.

  1. Beginnen wir zunächst NICHT mit dem, was "ich" denke, was "Sie" denken oder was noch ein anderer Buchautor denkt. Beginnen wir mit den HTTP-Spezifikationen, dh RFC 7231.

    • RFC 7231, Abschnitt 4.3.5 DELETE erwähnte zufällig nur, dass eine erfolgreiche Antwort 2xx sein sollte, rief jedoch nicht auf, was ein nachfolgendes DELETE erhalten würde. Also lasst uns tiefer graben.
    • RFC 7231, Abschnitt 6.5.4 404 Nicht gefunden besagt, dass die 404-Antwort für eine Ressource nicht vorhanden ist. Da keine bestimmte http-Methode (insbesondere nicht DELETE) zur anderweitigen Behandlung aufgerufen wird, können wir intuitiv (und zu Recht) den Eindruck gewinnen, dass meine Anfrage DELETE /some/resource/which/does/not/existzu einer 404 führen sollte. Dann DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/agokönnte genauso gut auch eine 404 zurückgegeben werden Warum sollte es DELETE /some/resource/i/deleted/five/seconds/agodann anders sein? "Aber wie wäre es mit Idempotenz?!", Kann ich hören, dass du das schreist. Moment mal, wir werden gleich darauf eingehen.
    • In der Vergangenheit war RFC 2616, veröffentlicht 1999, die am häufigsten referenzierte HTTP 1.1-Spezifikation. Leider war die Beschreibung der Idempotenz vage , was Raum für all diese Debatten lässt. Diese Spezifikation wurde jedoch durch RFC 7231 ersetzt. Zitiert aus RFC 7231, Abschnitt 4.2.2 Idempotente Methoden , Hervorhebung von mir:

      Eine Anforderungsmethode wird als "idempotent" betrachtet, wenn die beabsichtigte Auswirkung mehrerer identischer Anforderungen mit dieser Methode auf den Server der Wirkung einer einzelnen solchen Anforderung entspricht. Von den durch diese Spezifikation definierten Anforderungsmethoden sind PUT-, DELETE- und sichere Anforderungsmethoden idempotent .

      Es steht also in den Spezifikationen geschrieben, dass es bei der Idempotenz nur um die Auswirkungen auf den Server geht. Das erste LÖSCHEN, das ein 204 zurückgibt, und das nachfolgende LÖSCHEN, das 404 zurückgibt, macht ein derart unterschiedlicher Statuscode das LÖSCHEN NICHT nicht idempotent. Die Verwendung dieses Arguments zur Rechtfertigung einer nachfolgenden Rückgabe ist einfach irrelevant.

  2. OK, es geht also nicht um Idempotenz. Aber dann könnte eine Folgefrage sein, was ist, wenn wir uns immer noch dafür entscheiden, 204 in nachfolgendem LÖSCHEN zu verwenden? Ist es o.k?

    Gute Frage. Die Motivation ist verständlich: Dem Kunden zu ermöglichen, sein beabsichtigtes Ergebnis zu erreichen, ohne sich um die Fehlerbehandlung sorgen zu müssen. Ich würde sagen, 204 in nachfolgendem DELETE zurückzugeben, ist eine weitgehend harmlose serverseitige "Notlüge", die die Clientseite nicht sofort erkennen wird. Deshalb machen ~ 25% der Leute das in freier Wildbahn und es scheint immer noch zu funktionieren. Denken Sie daran, dass eine solche Lüge als semantisch seltsam angesehen werden kann, da sie GET /non-exist404 zurückgibt, aber DELETE /non-exist204 ergibt. Zu diesem Zeitpunkt würde der Kunde herausfinden, dass Ihr Service nicht vollständig mit Abschnitt 6.5.4 übereinstimmt. 404 Nicht gefunden .

    Ich möchte jedoch darauf hinweisen, dass der von RFC 7231 angedeutete beabsichtigte Weg, dh die Rückgabe von 404 bei nachfolgendem LÖSCHEN, überhaupt kein Problem sein sollte. 3x mehr Entwickler haben sich dafür entschieden, und haben Sie jemals einen größeren Vorfall oder eine Beschwerde gehört, die von einem Kunden verursacht wurde, der 404 nicht verarbeiten konnte? Vermutlich nein, und das liegt daran, dass jeder anständige Client, der HTTP DELETE (oder eine andere HTTP-Methode) implementiert, nicht blind davon ausgehen würde, dass das Ergebnis immer 2xx erfolgreich sein würde. Sobald der Entwickler über die Fehlerbehandlung nachdenkt, ist 404 Not Found einer der ersten Fehler, die in den Sinn kommen. Zu diesem Zeitpunkt würde er / sie wahrscheinlich die Schlussfolgerung ziehen, dass es für eine HTTP-DELETE-Operation semantisch sicher ist, einen 404-Fehler zu ignorieren. Und sie haben es getan.

Problem gelöst.

RayLuo
quelle
2
+1 "Idempotenz dreht sich alles um die Auswirkungen auf den Server". Sorgfältig beantwortet. Gut gemacht! Ich bin ein 404-Gläubiger für nachfolgende DELETE-Anfragen.
Nwayve
11

Erstes LÖSCHEN : 200 oder 204.

Nachfolgende LÖSCHEN : 200 oder 204.

Begründung : DELETE sollte idempotent sein. Wenn Sie bei einem zweiten LÖSCHEN 404 zurückgeben, ändert sich Ihre Antwort von einem Erfolgscode in einen Fehlercode . Das Client-Programm kann unter der Annahme, dass das LÖSCHEN fehlgeschlagen ist, falsche Aktionen ausführen.

Beispiel :

  • Angenommen, Ihre DELETE-Operation ist Teil einer mehrstufigen Operation (oder einer "Saga"), die vom Client-Programm ausgeführt wird.
  • Das Client-Programm kann beispielsweise eine mobile App sein, die eine Banküberweisung ausführt.
  • Angenommen, das Client-Programm hat eine automatische Wiederholung für eine DELETE-Operation (dies ist sinnvoll, da DELETE idempotent sein soll).
  • Angenommen, das erste DELETE wurde erfolgreich ausgeführt, aber die 200-Antwort ging auf dem Weg zum Client-Programm verloren.
  • Das Client-Programm wiederholt das LÖSCHEN.
  • Wenn der zweite Versuch 404 zurückgibt, kann das Client-Programm die Gesamtoperation aufgrund dieses Fehlercodes abbrechen.
  • Da das erste DELETE jedoch erfolgreich auf dem Server ausgeführt wurde, befindet sich das System möglicherweise in einem inkonsistenten Zustand .
  • Wenn der zweite Versuch 200 oder 204 zurückgibt, wird das Client-Programm wie erwartet fortgesetzt.

Um die Verwendung dieses Ansatzes zu veranschaulichen, enthält der HTTP-API-Styleguide für PayPal die folgende Richtlinie:

LÖSCHEN: Diese Methode SOLLTE den Statuscode 204 zurückgeben, da in den meisten Fällen kein Inhalt zurückgegeben werden muss, da die Anforderung das Löschen einer Ressource ist und diese erfolgreich gelöscht wurde.

Da die DELETE-Methode ebenfalls idempotent sein MUSS, MUSS sie immer noch 204 zurückgeben, selbst wenn die Ressource bereits gelöscht wurde. Normalerweise ist es dem API-Konsumenten egal, ob die Ressource im Rahmen dieses Vorgangs oder zuvor gelöscht wurde. Dies ist auch der Grund, warum 204 anstelle von 404 zurückgegeben werden sollte.

Paulo Merson
quelle
1
Die Frage ist, was für den Client wichtig ist, dass er die Ressource gelöscht hat oder dass die Ressource gelöscht wurde. Was ist, wenn ein anderer Client die Ressource während der Saga gelöscht hat? Möchten Sie wirklich scheitern, wenn das Ziel des Kunden erreicht wurde?
Darrel Miller
1
@DarrelMiller Guter Punkt. Was wichtiger ist, hängt vom Geschäftskontext ab. Im Allgemeinen würde ich bei einem zweiten DELETE-Versuch lieber 204 zurückgeben, selbst wenn die Ressource von einem anderen Client gelöscht wurde. Ich möchte nicht, dass der Service fehlschlägt (dh 404), da das Ziel des Kunden erreicht wurde.
Paulo Merson
2
Wie bereits erwähnt, ist Idempotenz nicht Ihr Antwortcode, sondern Ihr Serverstatus.
Niranjan
@Niranjan Ich bin damit einverstanden, dass es bei der Idempotenz um den Serverstatus geht, aber ein anderer Antwortcode kann den Client dazu veranlassen, den Serverstatus unnötig zu ändern, indem eine laufende Saga abgebrochen wird.
Paulo Merson
@Paulo Merson Welchen Code geben Sie zurück, wenn der Client die Löschung eines NIE vorhandenen Elements anfordert? 204? oder 404? Wenn Sie immer 204 zurückgeben, was bringt es, den Rückkehrcode zu überprüfen?
Französisch