REST, HTTP DELETE und Parameter

135

Ist die Bereitstellung von Parametern für eine HTTP-DELETE-Anforderung nicht REST-fähig?


Mein Szenario ist, dass ich das Modell "Sind Sie sicher, dass Sie das löschen möchten?" Szenario. In einigen Fällen deutet der Status der Ressource darauf hin, dass das angeforderte Löschen möglicherweise ungültig ist. Sie können sich wahrscheinlich selbst einige Szenarien vorstellen, in denen eine Bestätigung eines Löschvorgangs erforderlich ist

Die Lösung, die wir gewählt haben, besteht darin, einen Parameter an die Löschanforderung zu übergeben, um anzuzeigen, dass es in Ordnung ist, mit dem Löschen fortzufahren ("? 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-Anforderung senden. Dies kann jedoch bei 409 fehlschlagen, und der Hauptteil der Antwort erklärt, warum. Ich sage, kann fehlschlagen, weil (aus Gründen, die es nicht wert sind, erklärt zu werden) in einigen Fällen kein Grund besteht, den Benutzer dazu aufzufordern.

(b) In Roys Dissertation gibt es keinen Hinweis darauf, dass dies gegen den Geist von REST verstößt. Warum sollte dies der Fall sein, da HTTP nur eine Implementierung von REST ist? Warum sollte die Übergabe von HTTP-Parametern von Bedeutung sein?


Kann mich jemand auf eine endgültige Aussage hinweisen, die den Grund festhält, warum dies nicht RESTful ist?

Wenn der Benutzer bei einer verwandten Frage nicht force_delete angibt, kehre ich zurück. Ist dies der 409 Conflictam besten geeignete Antwortcode?


Nachverfolgen

Nach einigen weiteren Untersuchungen denke ich, dass das Hinzufügen von Parametern zum DELETE gegen mehrere Prinzipien verstoßen kann.

Das erste ist, dass die Implementierung möglicherweise gegen die "Uniform Interface" verstößt (siehe Abschnitt 5.1.5 von Roys Dissertation

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

Sie könnten auch argumentieren, dass es gegen den "5.1.2 Client-Server" verstößt, da der Bestätigungsdialog wirklich ein UI-Problem darstellt und wiederum nicht alle Clients das Löschen bestätigen möchten.

Vorschläge jemand?

Chris McCauley
quelle
1
Ihre URL für Roys Dissertation enthält ein ")", das eine 404 verursacht . Ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm funktioniert.
NuclearPeon

Antworten:

78

Nein, es ist nicht RESTful. Der einzige Grund, warum Sie ein Verb ( force_delete) in den URI einfügen sollten, besteht darin, dass Sie GET / POST-Methoden in einer Umgebung überladen müssten, in der PUT / DELETE-Methoden nicht verfügbar sind. Nach Ihrer Verwendung der DELETE-Methode ist dies nicht der Fall.

Der HTTP-Fehlercode 409/Conflictsollte in Situationen verwendet werden, in denen ein Konflikt vorliegt, der den RESTful-Dienst daran hindert, den Vorgang auszuführen. Es besteht jedoch weiterhin die Möglichkeit, dass der Benutzer den Konflikt möglicherweise selbst lösen kann. Eine Bestätigung vor dem Löschen (wenn es keine echten Konflikte gibt, die das Löschen verhindern würden) ist an sich kein Konflikt, da nichts die API daran hindert, den angeforderten Vorgang auszuführen.

Wie Alex sagte (ich weiß nicht, wer ihn herabgestuft hat, er ist korrekt), sollte dies in der Benutzeroberfläche behandelt werden, da ein RESTful-Service als solcher nur Anfragen verarbeitet und daher zustandslos sein sollte (dh er darf sich nicht auf Bestätigungen durch Halten stützen alle serverseitigen Informationen zu einer Anfrage).

Zwei Beispiele dafür sind:

  • Pre-HTML5 : * Zeigen Sie dem Benutzer einen JS-Bestätigungsdialog an und senden Sie die Anforderung nur, wenn der Benutzer dies bestätigt
  • HTML5 : * Verwenden Sie ein Formular mit der Aktion LÖSCHEN, bei dem das Formular nur die Schaltflächen "Bestätigen" und "Abbrechen" enthält ("Bestätigen" ist die Schaltfläche "Senden").

(*) Bitte beachten Sie, dass HTML-Versionen vor 5 die HTTP-Methoden PUT und DELETE nicht nativ unterstützen. Die meisten modernen Browser können diese beiden Methoden jedoch über AJAX-Aufrufe ausführen. In diesem Thread finden Sie Details zur browserübergreifenden Unterstützung.


Update (basierend auf zusätzlichen Untersuchungen und Diskussionen):

Das Szenario, in dem der Dienst das force_delete=trueVorhandensein des Flags erfordern würde, verstößt gegen die einheitliche Schnittstelle, wie sie in der Dissertation von Roy Fielding definiert ist. Auch per HTTP RFC , die DELETE - Methode auf dem Ursprungsserver außer Kraft gesetzt werden kann (Client), was bedeutet , dass dies nicht auf dem Zielserver (Service) durchgeführt wird.

Sobald der Dienst eine DELETE-Anforderung erhält, sollte er diese verarbeiten, ohne dass eine zusätzliche Bestätigung erforderlich ist (unabhängig davon, ob der Dienst den Vorgang tatsächlich ausführt).

Mäuse
quelle
2
Können Sie erklären, gegen welche REST-Einschränkung verstoßen wird? In Anbetracht der Tatsache, dass URIs für den Client undurchsichtig sein sollten, warum werden Ihrer Meinung nach die Erwartungen des Clients nicht erfüllt, wenn ein HTTP-LÖSCHEN verwendet wird, das eine Ressource löscht, eine andere jedoch nicht löscht? Ich bin mir nicht sicher, ob 409 der beste Statuscode für die Rückgabe ist, aber abgesehen davon, dass es sich um eine seltsame Implementierung handelt, kann ich keine REST-Einschränkungen finden, die verletzt werden.
Darrel Miller
2
@Darrel: (imho) Es verletzt die einheitliche Schnittstelle durch die DELETE-Methode, die nicht den HTTP-Standards entspricht. Stellen Sie sich einen REST-Client vor, der einen Standard-REST-Service voraussetzt. Wie wird der Service dem Client mitteilen, dass er hinzugefügt werden muss force_delete=true? Gemäß HTTP-RFC kann die DELETE-Methode auf dem Ursprungsserver (Client) überschrieben werden, was bedeutet, dass dies nicht auf dem Zielserver (Dienst) erfolgt. Mein Verständnis ist also, dass der Dienst, sobald er eine DELETE-Anforderung erhält, diese ohne Bestätigung verarbeiten sollte (unabhängig davon, ob der Dienst den Vorgang tatsächlich ausführt).
MicE
1
@Chris, zu Ihrem zweiten Punkt: Ja, das ist auch mein Verständnis, dh, dass der Staat einen echten Konflikt vorschlägt und keine Bestätigung benötigt. Ich habe gerade das Update bemerkt, das Sie in Ihrer Frage durchgeführt haben, und ich stimme zu - während ich es selbst untersuchte, kam ich zu dem gleichen Schluss (dass dies die einheitliche Oberfläche verletzt und dass die Bestätigung auf dem Client / der Benutzeroberfläche erfolgen sollte Seite). Ich bin hier auch auf einen sehr interessanten Thread gestoßen
MicE
2
@MicE Ich stimme Ihnen weitgehend zu, dass dies nicht der ideale Weg ist, um mit diesem Szenario umzugehen. Ich bin nur ein bisschen wählerisch in Bezug auf das Label "Es ist nicht RESTful". Für eine Weile wurde dieser Satz hier auf alles geworfen. Es wäre jedoch möglich, Regeln für einen Medientyp zu definieren, die besagen, wenn Sie versuchen, eine Ressource zu LÖSCHEN und eine Fehlermeldung erhalten (ich würde sagen, 403 verboten wäre besser als 409), sollte der Client versuchen, eine verwandte Ressource zu LÖSCHEN durch Anheften eines "force_delete = true". In gewisser Weise ist es ein bisschen wie eine Autorisierung. Führen Sie GET aus, holen Sie sich 401, fügen Sie den Auth-Header hinzu und rufen Sie erneut ab.
Darrel Miller
2
@Darrel: das ist ein sehr guter Punkt, danke. Und ich habe gesehen, wie Leute selbst das nicht RESTful- Label geworfen haben . Es kann vorkommen, dass die Barriere zwischen Diensten und Webanwendungen heutzutage sehr neblig wird, sodass eine Gruppe von Personen dies aus der Sicht eines reinen Dienstes sehen kann, während andere dies aus einer gemischten Sicht der Anwendung / des Dienstes sehen. Das ist, glaube ich, wo die eigentliche Frage nach der Bestätigung ins Spiel kommt. @ Chris: aktualisiert - danke Sir für ein sehr interessantes Thema und eine Diskussion!
MicE
35

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

Ist es sinnvoll, force_delete = true anzugeben, wenn dies die API eines Programms wäre? Wenn jemand ein Skript zum Löschen dieser Ressource schrieb, möchten Sie ihn zwingen, force_delete = true anzugeben, um die Ressource tatsächlich zu löschen?

Alex Rockwell
quelle
Der erste Absatz Ihrer Antwort ist Ihre Meinung, und ich respektiere dies, aber Sie haben in der Literatur nicht auf etwas hingewiesen, das die Verwendung des URI wie folgt verbietet - er identifiziert immer noch die Ressource und das am besten geeignete HTTP-Verb wird verwendet. Als Antwort auf Ihre Fragen; ja es würde immer noch Sinn machen (meiner Meinung nach). Ich würde erwarten, dass ein Skript (möglicherweise basierend auf CURL) die 409-Antwort respektiert und dem Benutzer vorschlägt, wie die Anfrage erneut gesendet werden kann - alles basierend auf meinem Antworttext
Chris McCauley
Ein guter Punkt zum Vergleichen der Web-API mit der API eines Programms. Dies ist oft eine gute Möglichkeit, um herauszufinden, ob eine API REST-fähig ist oder nicht.
Laurent
18

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

  1. In SQL akzeptiert der Befehl DELETE einen Parameter "CASCADE", mit dem Sie festlegen können, dass auch abhängige Objekte gelöscht werden sollen. Dies ist ein Beispiel für einen DELETE-Parameter, der sinnvoll ist, aber 'man rm' könnte andere bereitstellen. Wie würden diese Fälle möglicherweise in REST / HTTP ohne Parameter implementiert?
  2. @Jan, es scheint eine etablierte Konvention zu sein, dass der Pfadteil der URL eine Ressource identifiziert, während der Querystring dies nicht tut (zumindest nicht unbedingt). Es gibt viele Beispiele: 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 von "unterschiedlichen Ansichten derselben Ressource" zu haben. ohne sich nicht-REST-fähigen Mechanismen wie der Aushandlung von HTTP-Inhalten zuzuwenden (was aus vielen Gründen unerwünscht sein kann).
Shay Rojansky
quelle
Vielen Dank, dass Sie dies zur Konversation hinzugefügt haben, auch wenn es keine große Konversation ist, da es Jahre dauert.
Silviot
6

Zusätzlich zu Alex 'Antwort:

Beachten Sie, dass http: // server / resource / id? Force_delete = true eine andere Ressource als http: // server / resource / id identifiziert . Zum Beispiel ist es ein großer Unterschied, ob Sie / customers /? Status = old oder / customers / löschen.

Jan.

Jan Algermissen
quelle
Ich bin anderer Meinung, es steht mir frei, mehrere URIs bereitzustellen, um dieselbe Ressource zu identifizieren.
Chris McCauley
18
Ja - jeder ist frei, ein Chaos zu machen :-)
Jan Algermissen
Die Angabe kanonischer URIs könnte dabei helfen: googlewebmastercentral.blogspot.com/2009/02/…
MicE
@Chris Es sollte nur einen URI geben, der eine Darstellung einer Ressource zurückgibt. Andere URIs können sich auf dasselbe Konzept beziehen, aber bei einem GET sollte ein 303 See Other zurückgegeben werden. Und nur um dem offensichtlichen Einwand entgegenzuwirken, sind /foo.xml und /foo.json zwei verschiedene Ressourcen.
Darrel Miller
@Darrell - stimme zu, aber das Format ist hier kein Problem. Das .format ist auch eine Konvention in Rails und anderen Frameworks, die nicht Teil von REST sind. Sie sollten die Inhaltsverhandlung in HTTP mit MIME oder Mikroformaten verwenden, um dies vollständig zu implementieren.
Chris McCauley