wake-up-neo.com

RESTful Alternativen zu DELETE Request Body

Während die HTTP 1.1-Spezifikation anscheinend allow Nachrichtentexte auf DELETE Requests enthält, scheint es so Geben Sie an, dass Server diese ignorieren sollen, da für sie keine Semantik definiert ist.

4.3 Nachrichtentext

Ein Server SOLLTE bei jeder Anfrage einen Nachrichtentext lesen und weiterleiten. Wenn die Anforderungsmethode keine definierte Semantik für einen Entity-Body enthält, MUSS der Message-Body bei der Bearbeitung der Anforderung ignoriert werden.

Ich habe bereits mehrere verwandte Diskussionen zu diesem Thema in SO und darüber hinaus besprochen, darunter:

Die meisten Diskussionen scheinen zu stimmen, dass das Bereitstellen eines Nachrichtentexts bei DELETE erlaubt ist, aber im Allgemeinen nicht empfohlen wird.

Außerdem habe ich in verschiedenen HTTP-Client-Bibliotheken einen Trend festgestellt, bei dem immer mehr Verbesserungen für diese Bibliotheken protokolliert werden, um Anforderungskörper in DELETE zu unterstützen. Die meisten Bibliotheken scheinen sich zu verpflichten, wenn auch gelegentlich mit ein wenig anfänglichem Widerstand.

In meinem Anwendungsfall müssen einige erforderliche Metadaten zu einem DELETE hinzugefügt werden (z. B. der "Grund" für das Löschen sowie einige andere für das Löschen erforderliche Metadaten). Ich habe die folgenden Optionen in Betracht gezogen, von denen keine vollständig angemessen und im Einklang mit den HTTP-Spezifikationen und/oder REST - Best Practices zu sein scheint:

  • Nachrichtentext - Die Spezifikation gibt an, dass Nachrichtentexte in DELETE keinen semantischen Wert haben. von HTTP-Clients nicht vollständig unterstützt; keine Standardpraxis
  • Benutzerdefinierte HTTP-Header - Das Erfordernis von benutzerdefinierten Headern ist im Allgemeinen gegen Standardpraktiken ; Ihre Verwendung ist mit dem Rest meiner API unvereinbar, für die keine benutzerdefinierten Header erforderlich sind. Außerdem ist keine gute HTTP-Antwort verfügbar, die auf ungültige benutzerdefinierte Headerwerte hinweist (wahrscheinlich eine separate Frage insgesamt).
  • Standard-HTTP-Header - Es sind keine Standard-Header geeignet
  • Abfrageparameter - Durch das Hinzufügen von Abfrageparametern wird der zu löschende Anforderungs-URI geändert. gegen Standardpraktiken
  • POST-Methode - (z. B. POST /resourceToDelete { deletemetadata }) POST ist keine semantische Option zum Löschen. POST stellt tatsächlich die gewünschte Gegenteil Aktion dar (d. H. POST erstellt Ressourcenuntergeordnete, aber ich muss die Ressource löschen)
  • Mehrere Methoden - Aufteilen der DELETE-Anforderung in zwei Operationen (z. B. PUT-Löschmetadaten, dann DELETE) Aufteilen einer atomaren Operation in zwei, wobei möglicherweise ein inkonsistenter Zustand verbleibt. Der Löschgrund (und andere verwandte Metadaten) sind nicht Teil der Ressourcendarstellung.

Meine erste Präferenz wäre wahrscheinlich, den Nachrichtentext zu verwenden, die zweite gegenüber benutzerdefinierten HTTP-Headern. Wie bereits erwähnt, weisen diese Ansätze jedoch einige Nachteile auf.

Gibt es Empfehlungen oder Best Practices, die den REST/HTTP-Standards entsprechen, um die erforderlichen Metadaten in DELETE-Anforderungen aufzunehmen? Gibt es andere Alternativen, die ich nicht in Betracht gezogen habe?

85
shelley

Trotz einiger Empfehlungen, den Nachrichtentext nicht für DELETE-Anforderungen zu verwenden, kann dieser Ansatz in bestimmten Anwendungsfällen angemessen sein. Dies ist der Ansatz, den wir letztendlich gewählt haben, nachdem wir die anderen in den Fragen/Antworten genannten Optionen bewertet und mit den Verbrauchern des Dienstes zusammengearbeitet haben.

Obwohl die Verwendung des Nachrichtentexts nicht ideal ist, passte auch keine der anderen Optionen perfekt. Der Anfragetext DELETE ermöglichte es uns, zusätzliche Daten/Metadaten, die für die DELETE-Operation benötigt wurden, einfach und klar mit einer Semantik zu versehen.

Ich wäre immer noch offen für andere Gedanken und Diskussionen, wollte aber den Kreis dieser Frage schließen. Ich schätze alle Gedanken und Diskussionen zu diesem Thema!

40
shelley

Was Sie zu wollen scheinen, ist eines von zwei Dingen, von denen keines ein reines DELETE ist:

  1. Sie haben zwei Operationen a PUT des Löschgrundes gefolgt von einem DELETE der Ressource. Nach dem Löschen ist der Inhalt der Ressource für niemanden mehr zugänglich. Der 'Grund' darf keinen Hyperlink zur gelöschten Ressource enthalten. Oder,
  2. Sie versuchen, eine Ressource zu ändern from state=active bis state=deleted mit der DELETE Methode. Ressourcen mit dem Status "Gelöscht" werden von Ihrer Haupt-API ignoriert, können jedoch von einem Administrator oder einer Person mit Datenbankzugriff gelesen werden. Dies ist zulässig - DELETE muss die Sicherungsdaten für eine Ressource nicht löschen, nur um die Ressource zu entfernen, die bei dieser URI verfügbar gemacht wurde.

Jede Operation, die einen Nachrichtentext für eine DELETE -Anforderung erfordert, kann in den allgemeinsten, einen POST, um alle erforderlichen Aufgaben mit dem Nachrichtentext auszuführen, und einen DELETE. Ich sehe keinen Grund, die Semantik von HTTP zu brechen.

12
Nicholas Shanks

In Anbetracht der Situation, die Sie haben, würde ich einen der folgenden Ansätze wählen:

  • PUT oder PATCH senden: Ich gehe davon aus, dass der Löschvorgang virtuell ist, da ein Löschgrund erforderlich ist. Daher halte ich das Aktualisieren des Datensatzes über eine PUT/PATCH-Operation für einen gültigen Ansatz, auch wenn es an sich keine DELETE-Operation ist.
  • Verwenden Sie die Abfrageparameter: Die Ressource uri wird nicht geändert. Ich denke tatsächlich, dass dies auch ein gültiger Ansatz ist. Bei der von Ihnen verknüpften Frage ging es darum, das Löschen nicht zuzulassen, wenn der Abfrageparameter fehlt. In Ihrem Fall hätte ich nur einen Standardgrund, wenn der Grund nicht in der Abfragezeichenfolge angegeben ist. Die Ressource ist weiterhin resource/:id. Sie können es für jeden Grund mit Link-Headern in der Ressource sichtbar machen (mit einem rel -Tag, um den Grund zu identifizieren).
  • Verwenden Sie einen separaten Endpunkt pro Grund: Verwenden Sie eine URL wie resource/:id/canceled. Dies ändert den Request-URI tatsächlich und ist definitiv nicht REST-konform. Auch hier können Link-Header dies auffindbar machen.

Denken Sie daran, dass REST kein Gesetz oder Dogma ist. Betrachten Sie es eher als Anleitung. Wenn es also Sinn macht, die Anleitung für Ihre Problemdomäne nicht zu befolgen, tun Sie das nicht. Stellen Sie einfach sicher, dass Ihre API Verbraucher werden über die Abweichung informiert.

7
codeprogression

Ich schlage vor, dass Sie die erforderlichen Metadaten als Teil der URI-Hierarchie selbst einbeziehen. Ein Beispiel (naiv):

Wenn Sie Einträge basierend auf einem Datumsbereich löschen müssen, anstatt das Start- und Enddatum im Text oder als Abfrageparameter zu übergeben, strukturieren Sie den URI so, dass Sie die erforderlichen Informationen als Teil des URI übergeben.

z.B.

DELETE /entries/range/01012012/31122012 - Alle Einträge zwischen dem 01. Januar 2012 und dem 31. Dezember 2012 löschen

Hoffe das hilft.

0
Suresh Kumar