147 Stimmen

REST, HTTP DELETE und Parameter

Gibt es irgendetwas an der Übergabe von Parametern an eine HTTP-DELETE-Anforderung, das nicht RESTful ist?

Mein Szenario ist, dass ich das Szenario "Sind Sie sicher, dass Sie das löschen wollen?" modelliere. In einigen Fällen deutet der Zustand der Ressource darauf hin, dass die angeforderte Löschung ungültig sein könnte. Sie können sich wahrscheinlich selbst einige Szenarien vorstellen, in denen eine Bestätigung des Löschens erforderlich ist

Die von uns gewählte Lösung besteht darin, der Löschanfrage einen Parameter zu übergeben, der angibt, dass die Löschung durchgeführt werden darf ("?force_delete=true").

z.B..

DELETE http://server/resource/id?force_delete=true

Ich glaube, dass es seitdem immer noch erholsam ist:

(a) Die Semantik von DELETE wird nicht geändert - der Benutzer kann weiterhin eine normale DELETE-Anfrage senden, aber diese kann scheitern mit 409 und der Text der Antwort wird erklären, warum. Ich sage "kann fehlschlagen", weil es (aus nicht erklärungsbedürftigen Gründen) in manchen Fällen keinen Grund gibt, den Benutzer aufzufordern.

(b) In Roys Dissertation gibt es keinen Hinweis darauf, dass dies gegen den Geist von REST verstößt - warum auch, denn HTTP ist nur eine Implementierung von REST, warum also sollte die Übergabe von HTTP-Parametern eine Rolle spielen?

Kann jemand mich auf eine definitive Aussage, die den Grund, warum dies nicht RESTful nagelt zeigen?

Auf eine verwandte Frage, wenn der Benutzer nicht angeben, force_delete dann bin ich zurück 409 Conflict - Ist das der am besten geeignete Antwortcode?

Weiterverfolgung

Nach weiteren Nachforschungen bin ich der Meinung, dass das Hinzufügen von Parametern zu DELETE mehrere Grundsätze verletzen könnte.

Die erste ist, dass die Implementierung möglicherweise gegen die "Einheitliche Schnittstelle" verstößt (siehe Abschnitt 5.1.5 von Roys Dissertation

Durch das Hinzufügen von "force_delete" fügen wir eine zusätzliche Einschränkung zu der bereits gut definierten DELETE-Methode hinzu. Diese Einschränkung ist nur für uns von Bedeutung.

Man könnte auch argumentieren, dass dies gegen "5.1.2 Client-Server" verstößt, da der Bestätigungsdialog eigentlich eine Frage der Benutzeroberfläche ist und wiederum nicht alle Clients die Löschung bestätigen wollen.

Hat jemand einen Vorschlag?

84voto

MicE Punkte 4912

Nein, es ist nicht RESTful. Der einzige Grund, warum Sie ein Verb ( force_delete ) in den URI ist, wenn Sie GET/POST-Methoden in einer Umgebung überladen müssen, in der PUT/DELETE-Methoden nicht verfügbar sind. Nach Ihrer Verwendung der DELETE-Methode zu urteilen, ist dies nicht der Fall.

HTTP-Fehlercode 409/Conflict sollte für Situationen verwendet werden, in denen ein Konflikt besteht, der den RESTful-Dienst daran hindert, den Vorgang auszuführen, aber immer noch die Möglichkeit besteht, dass der Benutzer den Konflikt selbst auflösen kann. Eine Bestätigung vor der Löschung (bei der es keine echten Konflikte gibt, die eine Löschung verhindern würden) ist per se kein Konflikt, da nichts die API daran hindert, den angeforderten Vorgang auszuführen.

Wie Alex sagte (ich weiß nicht, wer ihn heruntergevotet hat, er hat Recht), sollte dies in der UI gehandhabt werden, da ein RESTful-Dienst als solcher nur Anfragen verarbeitet und daher zustandslos sein sollte (d.h. er darf sich nicht auf Bestätigungen verlassen, indem er serverseitige Informationen über eine Anfrage speichert).

Zwei Beispiele dafür, wie man dies in der Benutzeroberfläche tun kann, wären:

  • vor-HTML5 * dem Benutzer einen JS-Bestätigungsdialog anzeigen und die Anfrage nur senden, wenn der Benutzer sie bestätigt
  • HTML5 ein Formular mit der Aktion DELETE verwenden, das nur die Schaltflächen "Bestätigen" und "Abbrechen" enthält ("Bestätigen" wäre die Schaltfläche "Senden")

(*) Bitte beachten Sie, dass HTML-Versionen vor Version 5 die HTTP-Methoden PUT und DELETE nicht von Haus aus unterstützen, die meisten modernen Browser können diese beiden Methoden jedoch über AJAX-Aufrufe ausführen. Siehe dieses Thema für Details zur Cross-Browser-Unterstützung.


Update (auf der Grundlage zusätzlicher Untersuchungen und Gespräche):

Das Szenario, in dem der Dienst die force_delete=true Flagge vorhanden sein muss, verstößt gegen die einheitliche Schnittstelle wie in der Dissertation von Roy Fielding definiert. Außerdem, wie in HTTP-RFC Die DELETE-Methode kann auf dem Ursprungsserver (Client) außer Kraft gesetzt werden, was bedeutet, dass dies auf dem Zielserver (Dienst) nicht geschieht.

Sobald der Dienst also eine DELETE-Anforderung erhält, sollte er sie ohne weitere Bestätigung verarbeiten (unabhängig davon, ob der Dienst den Vorgang tatsächlich ausführt).

38voto

Alex Rockwell Punkte 1404

Ich denke, das ist nicht erholsam. Ich glaube nicht, dass der Restful-Dienst die Anforderung erfüllen sollte, den Benutzer zu zwingen, ein Löschen zu bestätigen. Ich würde dies in der Benutzeroberfläche behandeln.

Ist die Angabe von force_delete=true sinnvoll, wenn es sich um die API eines Programms handelt? Wenn jemand ein Skript zum Löschen dieser Ressource schreiben würde, würden Sie ihn dann zwingen wollen, force_delete=true anzugeben, um die Ressource tatsächlich zu löschen?

21voto

Shay Rojansky Punkte 13283

Es ist eine alte Frage, aber hier sind einige Kommentare...

  1. In SQL akzeptiert der DELETE-Befehl einen Parameter "CASCADE", mit dem Sie angeben können, dass abhängige Objekte ebenfalls gelöscht werden sollen. Dies ist ein sinnvolles Beispiel für einen DELETE-Parameter, aber "man rm" könnte noch weitere liefern. Wie könnten diese Fälle in REST/HTTP ohne einen Parameter implementiert werden?
  2. @Jan, es scheint eine gängige Konvention zu sein, dass der Pfadteil der URL eine Ressource identifiziert, während der Querystring dies nicht tut (zumindest nicht unbedingt). Beispiele dafür gibt es zuhauf: dieselbe Ressource in einem anderen Format abrufen, bestimmte Felder einer Ressource abrufen usw. Wenn wir den Querystring als Teil der Ressourcenkennung betrachten, ist es unmöglich, ein Konzept der "verschiedenen Sichten auf dieselbe Ressource" zu haben, ohne auf nicht-RESTful-Mechanismen wie HTTP-Content-Negotiation zurückzugreifen (was aus vielen Gründen unerwünscht sein kann).

5voto

Jan Algermissen Punkte 4862

Ergänzend zu Alex' Antwort:

Beachten Sie, dass http://server/resource/id?force_delete=true identifiziert eine andere Ressource als http://server/resource/id . Es ist zum Beispiel ein großer Unterschied, ob Sie die /customers/?status=old o /customers/ .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X