Während die HTTP 1.1 - Spezifikation zu scheint erlauben Nachrichtentexte auf DELETE - Anfragen, so scheint es , um anzuzeigen , dass die Server ignorieren sollten , da es keine definierte Semantik für sie ist.
4.3 Nachrichtentext
Ein Server sollte auf jede 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.
Ich habe bereits mehrere verwandte Diskussionen zu diesem Thema auf SO und darüber hinaus besprochen, wie zum Beispiel:
- Ist ein Entitätskörper für eine HTTP-DELETE-Anforderung zulässig?
- Nutzdaten von HTTP-Anforderungsmethoden
- HTTP GET mit Anforderungshauptteil
Die meisten Diskussionen scheinen darin übereinzustimmen, dass das Bereitstellen eines Nachrichtentexts auf einem DELETE zulässig ist , dies wird jedoch im Allgemeinen nicht empfohlen.
Außerdem habe ich einen Trend in verschiedenen HTTP-Client-Bibliotheken festgestellt, bei denen immer mehr Verbesserungen für diese Bibliotheken protokolliert werden, um Anforderungskörper auf 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 zum Löschen erforderliche Metadaten). Ich habe die folgenden Optionen in Betracht gezogen, von denen keine völlig angemessen erscheint und mit den HTTP-Spezifikationen und / oder REST-Best Practices übereinstimmt:
- 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 benutzerdefinierter Header verstößt im Allgemeinen gegen Standardpraktiken . Ihre Verwendung ist nicht mit dem Rest meiner API vereinbar, für die keine benutzerdefinierten Header erforderlich sind. Außerdem ist keine gute HTTP-Antwort verfügbar, um schlechte benutzerdefinierte Header-Werte anzuzeigen (wahrscheinlich eine separate Frage insgesamt).
- Standard-HTTP-Header - Es sind keine Standard-Header geeignet
- Abfrageparameter - Hinzufügen von Abfrage params ändert tatsächlich die Request-URI gelöscht werden; gegen Standardpraktiken
- POST-Methode - (z. B.
POST /resourceToDelete { deletemetadata }
) POST ist keine semantische Option zum Löschen. POST stellt tatsächlich die entgegengesetzte gewünschte Aktion dar (dh POST erstellt Ressourcenuntergebene; ich muss die Ressource jedoch löschen). - Mehrere Methoden - Die Aufteilung der DELETE-Anforderung in zwei Operationen (z. B. PUT-Löschmetadaten, dann DELETE) teilt eine atomare Operation in zwei auf, wodurch möglicherweise ein inkonsistenter Zustand verbleibt. Der Löschgrund (und andere verwandte Metadaten) sind nicht Teil der Ressourcendarstellung selbst.
Meine erste Präferenz wäre wahrscheinlich die Verwendung des Nachrichtentexts nach benutzerdefinierten HTTP-Headern. Wie bereits erwähnt, weisen diese Ansätze jedoch einige Nachteile auf.
Gibt es Empfehlungen oder Best Practices im Einklang mit den REST / HTTP-Standards, um solche erforderlichen Metadaten in DELETE-Anforderungen aufzunehmen? Gibt es andere Alternativen, die ich nicht in Betracht gezogen habe?
quelle
Jersey
erlauben keinen Body fürdelete
Anfragen.Antworten:
Trotz einiger Empfehlungen, den Nachrichtentext nicht für DELETE-Anforderungen zu verwenden, kann dieser Ansatz in bestimmten Anwendungsfällen geeignet 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, war auch keine der anderen Optionen perfekt geeignet. Mit dem Anforderungshauptteil DELETE konnten wir einfach und klar Semantik für zusätzliche Daten / Metadaten hinzufügen, die für die DELETE-Operation erforderlich waren.
Ich wäre immer noch offen für andere Gedanken und Diskussionen, wollte aber den Kreis dieser Frage schließen. Ich schätze die Gedanken und Diskussionen aller zu diesem Thema!
quelle
Was Sie zu wollen scheinen, ist eines von zwei Dingen, von denen keines rein ist
DELETE
:PUT
der Löschgründe, gefolgt von einemDELETE
der Ressourcen. 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,state=active
bis zu ändern . Ressourcen mit dem Status = gelöscht werden von Ihrer Haupt-API ignoriert, können jedoch möglicherweise von einem Administrator oder einer Person mit Datenbankzugriff gelesen werden. Dies ist zulässig. Sie müssen die Sicherungsdaten für eine Ressource nicht löschen, sondern nur die an dieser URI verfügbare Ressource entfernen.state=deleted
DELETE
DELETE
Jede Operation, die einen Nachrichtentext für eine
DELETE
Anforderung erfordert, kann im Allgemeinen in a unterteilt werdenPOST
, um alle erforderlichen Aufgaben mit dem Nachrichtentext auszuführen, und aDELETE
. Ich sehe keinen Grund, die Semantik von HTTP zu brechen.quelle
PUT
Vernunft erfolgreich ist und dieDELETE
Ressource ausfällt? Wie kann ein inkonsistenter Zustand verhindert werden?In Anbetracht Ihrer Situation würde ich einen der folgenden Ansätze verfolgen:
resource/:id
. Sie können es mit Link-Headern in der Ressource für jeden Grund erkennbar machen (mit einemrel
Tag auf jedem, um den Grund zu identifizieren).resource/:id/canceled
. Dies ändert tatsächlich den Request-URI und ist definitiv nicht RESTful. 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 sinnvoll ist, die Anweisungen für Ihre Problemdomäne nicht zu befolgen, tun Sie dies nicht. Stellen Sie einfach sicher, dass Ihre API-Konsumenten über die Abweichung informiert sind.
quelle
/orders/:id
würde also dieselbe Ressource wie zurückgeben/orders/:id?exclude=orderdetails
. Die Abfragezeichenfolge gibt dem Server nur Hinweise - in diesem Fall, um Bestelldetails in der Antwort auszuschließen (falls unterstützt). Wenn Sie DELETE an/orders/:id
oder/orders/:id?reason=canceled
oder senden/orders/:id?reason=bad_credit
, agieren Sie weiterhin auf dieselbe zugrunde liegende Ressource. Um eine "einheitliche Schnittstelle" beizubehalten, hätte ich einen Standardgrund, so dass das Senden des Abfrageparameters nicht erforderlich ist./foo?123
Wenn Sie eine DELETE-Anforderung an senden , bedeutet dies, dass Sie eine andere Ressource löschen, als wenn Sie DELETE an senden würden/foo?456
.Ich schlage vor, Sie fügen die erforderlichen Metadaten als Teil der URI-Hierarchie selbst hinzu. Ein Beispiel (naiv):
Wenn Sie Einträge basierend auf einem Datumsbereich löschen müssen, anstatt das Start- und Enddatum im Hauptteil 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
- Löschen Sie alle Einträge zwischen dem 1. Januar 2012 und dem 31. Dezember 2012Hoffe das hilft.
quelle
range
in Abfrageparametern oder Nutzdaten angegebenen Werte zu haben, die das Kernstück dieser Frage sind: Um den Best-Practice-Ansatz für das Problem zu verstehen, würde ich sagen, dass dies nicht der Fall ist.