Löschen Sie mehrere Datensätze mit REST

95

Was ist die REST-vollständige Methode zum Löschen mehrerer Elemente?

Mein Anwendungsfall ist, dass ich eine Backbone-Sammlung habe, in der ich mehrere Elemente gleichzeitig löschen kann. Die Optionen scheinen zu sein:

  1. Senden Sie eine DELETE-Anfrage für jeden einzelnen Datensatz (was eine schlechte Idee ist, wenn möglicherweise Dutzende von Elementen vorhanden sind).
  2. Senden Sie ein DELETE, bei dem die zu löschenden IDs in der URL aneinandergereiht sind (dh "/ records / 1; 2; 3").
  3. Senden Sie auf nicht-REST-Weise ein benutzerdefiniertes JSON-Objekt, das die zum Löschen markierten IDs enthält.

Alle Optionen sind nicht ideal.

Dies scheint eine Grauzone der REST-Konvention zu sein.

Donald Taylor
quelle
3
Mögliches Duplikat von Restful Weg zum Löschen einer Reihe von Elementen
Luka Žitnik

Antworten:

89
  1. Ist eine praktikable RESTful-Wahl, hat aber offensichtlich die von Ihnen beschriebenen Einschränkungen.
  2. Tu das nicht. Es würde von Vermittlern so ausgelegt werden, dass es "LÖSCHEN der (einzelnen) Ressource um /records/1;2;3" bedeutet. Eine 2xx-Antwort darauf kann dazu führen, dass sie ihren Cache von löschen /records/1;2;3. nicht spülen /records/1, /records/2oder /records/3; Proxy eine 410 Antwort für /records/1;2;3oder andere Dinge, die aus Ihrer Sicht nicht sinnvoll sind.
  3. Diese Wahl ist am besten und kann RESTful getroffen werden. Wenn Sie eine API erstellen und Massenänderungen an Ressourcen zulassen möchten, können Sie REST verwenden, um dies zu tun, aber genau wie ist für viele nicht sofort offensichtlich. Ein Verfahren besteht darin , eine ‚Änderungsanforderung‘ Ressource zu erstellen (zB durch einen Körper POSTen wie records=[1,2,3]zu /delete-requests) und abfragen , die erstellte Ressource (spezifiziert durch die LocationHeader der Antwort) , um herauszufinden , ob Ihr Antrag angenommen wurde, abgelehnt, ist im Gange oder abgeschlossen hat. Dies ist nützlich für langfristige Vorgänge. Eine weitere Möglichkeit ist es , eine senden PATCHAnfrage an die Liste Ressource ,/records, dessen Hauptteil eine Liste von Ressourcen und Aktionen enthält, die für diese Ressourcen ausgeführt werden sollen (in welchem ​​Format auch immer Sie unterstützen möchten). Dies ist nützlich für schnelle Vorgänge, bei denen der Antwortcode für die Anforderung das Ergebnis des Vorgangs anzeigen kann.

Alles kann erreicht werden, während die Einschränkungen von REST eingehalten werden. Normalerweise besteht die Antwort darin, das "Problem" in eine Ressource zu verwandeln und ihr eine URL zu geben.
Batch-Vorgänge wie das Löschen hier oder das POSTEN mehrerer Elemente in eine Liste oder das gleiche Bearbeiten einer Reihe von Ressourcen können alle ausgeführt werden, indem eine Liste "Batch-Vorgänge" erstellt und Ihr neuer Vorgang in diese Liste gestellt wird.

Vergessen Sie nicht, REST ist nicht der einzige Weg, um ein Problem zu lösen. „REST“ ist nur ein Architekturstil und Sie nicht haben , um sich daran zu halten (aber Sie verlieren , bestimmte Vorteile des Internet , wenn Sie dies nicht tun). Ich schlage vor, Sie sehen sich diese Liste der HTTP-API-Architekturen an und wählen die für Sie passende aus. Machen Sie sich einfach bewusst, was Sie verlieren, wenn Sie eine andere Architektur wählen, und treffen Sie eine fundierte Entscheidung basierend auf Ihrem Anwendungsfall.

Gibt es einige schlechte Antworten auf diese Frage zu Mustern für die Verarbeitung von Stapeloperationen in REST-Webdiensten? die viel zu viele positive Stimmen haben, aber auch gelesen werden sollten.

Nicholas Shanks
quelle
2
Es ist nicht Ihr Server, über den Sie sich Sorgen machen müssen, sondern Vermittler, CDNs, Caching-Proxys usw. Das Internet ist ein mehrschichtiges System. Das ist der Grund , warum es so gut funktioniert. Roy bestimmte, welche Aspekte des Systems für seinen Erfolg notwendig waren, und nannte sie REST. Wenn Sie eine DELETEAnfrage stellen, wird alles, was zwischen dem Anforderer und dem Server liegt, denken, dass eine einzelne Ressource unter der angegebenen URL gelöscht wird. Abfragezeichenfolgen sind undurchsichtige Teile der URL zu diesen Geräten. Es spielt also keine Rolle, wie Sie Ihre API angeben. Sie sind nicht mit diesem Wissen vertraut und können sich daher nicht anders verhalten.
Nicholas Shanks
3
/ records / 1; 2; 3 wird nicht funktionieren, wenn Sie aufgrund von URI-Längenbeschränkungen viele Ressourcen zum Löschen haben
dukethrash
3
Beachten Sie, dass einige Vermittler den Körper möglicherweise nicht weiterleiten, wenn Sie DELETE und eine Stelle in Betracht ziehen, die die zu bereinigenden Ressourcen definiert. Außerdem können einige HTTP-Clients einem DELETE keinen Text hinzufügen. Siehe stackoverflow.com/questions/299628/…
Luke Puplett
3
@LukePuplett Ich würde einfach sagen, dass das Übergeben eines Anforderungshauptteils mit einer DELETEAnforderung verboten ist. Tu es nicht. Wenn du das tust, werde ich deine Kinder essen. Mampf mampf Mampf.
Nicholas Shanks
3
Das Problem mit dem Argument für # 3 ist, dass es die gleiche Strafe trägt wie das Gegenargument gegen # 2. Das Erstellen von Ressourcen zum Löschen ist nicht etwas, mit dem Upstream-Proxys umgehen können - dasselbe Gegenargument, das gegen Ansatz 2 vorgebracht wird.
LB2
16

Wenn ein GET /records?filteringCriteriaArray aller Datensätze zurückgegeben wird, die den Kriterien entsprechen, DELETE /records?filteringCriteriakönnen alle diese Datensätze gelöscht werden.

In diesem Fall wäre die Antwort auf Ihre Frage DELETE /records?id=1&id=2&id=3.

Martin Ždila
quelle
1
Ich bin auch zu diesem Schluss gekommen: Drehen Sie das Verb einfach auf das, was Sie tun möchten. Ich verstehe nicht, wie das, was für GET gilt, nicht für DELETE gilt.
Luke Puplett
9
GET /records?id=1&id=2&id=3bedeutet nicht "die drei Datensätze mit den IDs 1, 2 und 3 abrufen", sondern "die einzelne Ressource mit URL-Pfad / Datensätzen abrufen? id = 1 & id = 2 & id = 3", was ein Bild einer Rübe sein könnte, ein einfacher Text Dokument mit der Nummer "42" auf Chinesisch oder möglicherweise nicht vorhanden.
Nicholas Shanks
Beachten Sie Folgendes: Zwei aufeinanderfolgende Anforderungen für /records?id=1und /records?id=2werden gesendet und ihre Antworten von einem Vermittler (z. B. Ihrem Browser oder ISP) zwischengespeichert. Wenn das Internet wusste, was Ihre Anwendung damit meinte, liegt es nahe, dass eine Anfrage /records?id=1&id=2vom Cache einfach durch Zusammenführen (irgendwie) der beiden bereits vorhandenen Ergebnisse zurückgegeben werden kann, ohne den Ursprungsserver fragen zu müssen. Das ist aber nicht möglich. /records?id=1&id=2ist möglicherweise ungültig (nur 1 ID pro Anfrage zulässig) oder gibt etwas völlig anderes zurück (eine Rübe).
Nicholas Shanks
Dies ist ein grundlegendes Problem beim Zwischenspeichern von Ressourcen. Wenn mein DBA den Status direkt mutiert hat, sind die Caches jetzt nicht mehr synchron. Sie geben ein vom Vermittler zurückgegebenes Beispiel 410 an, aber 410 dient zum dauerhaften Entfernen. Beim LÖSCHEN löscht ein Cache möglicherweise seinen Steckplatz für diese URL, sendet jedoch keine 410 oder 404, da er nicht weiß, ob ein DBA vorhanden ist hat die Ressource nicht einfach sofort wieder an den Ursprung zurückgesetzt.
Luke Puplett
4
@NicholasShanks Ich bin wirklich anderer Meinung. Wenn die Ergebnisse zwischengespeichert werden, liegt dies am Server. Und wenn Sie über das Design der API sprechen, sind Sie hoffentlich derjenige, der den Code für den Server schreibt. Unabhängig davon, ob Sie id[]=1&id[]=2oder id=1&id=2in der Abfragezeichenfolge ein Array von Werten darstellen, repräsentiert diese Abfragezeichenfolge genau das. Und ich denke, es ist äußerst üblich und empfehlenswert, dass die Abfragezeichenfolge einen Filter darstellt. Außerdem , wenn Sie für Löschungen und Aktualisierungen ermöglichen, nicht cachen nicht die GETAnfragen. Wenn Sie dies tun, behalten Clients den veralteten Status bei.
Joseph Nields
8

Ich denke, Mozilla Storage Service SyncStorage API v1.5 ist eine gute Möglichkeit, mehrere Datensätze mit REST zu löschen.

Löscht eine gesamte Sammlung.

DELETE https://<endpoint-url>/storage/<collection>

Löscht mehrere BSOs aus einer Sammlung mit einer einzigen Anforderung.

DELETE https://<endpoint-url>/storage/<collection>?ids=<ids>

ids : Löscht BSOs aus der Sammlung, deren IDs in der durch Kommas getrennten Liste enthalten sind. Es können maximal 100 IDs angegeben werden.

Löscht das BSO an der angegebenen Stelle.

DELETE https://<endpoint-url>/storage/<collection>/<id>

http://moz-services-docs.readthedocs.io/en/latest/storage/apis-1.5.html#api-instructions

Bootsoon
quelle
Dies scheint eine gute Lösung zu sein. Ich denke, wenn Mozilla denkt, dass es richtig ist, dann muss es sein? Die einzige Frage ist dann die Fehlerbehandlung. Angenommen, sie bestehen? IDs = 1,2,3 und ID 3 existiert nicht. Löschen Sie 1 und 2 und antworten Sie dann mit 200, weil der Anforderer möchte, dass 3 weg ist und es nicht da ist, also spielt es keine Rolle? oder was ist, wenn sie berechtigt sind, 1, aber nicht 2 zu löschen ... löschen Sie nichts und antworten mit einem Fehler oder löschen Sie, was Sie können und lassen Sie die anderen ...
tempcke
Normalerweise werde ich eine erfolgreiche Antwort zurückgeben, da der Endzustand unabhängig davon der gleiche ist. Dies vereinfacht auch die Logik auf dem Client, da dieser Fehlerstatus nicht mehr behandelt werden muss. Was den Autorisierungsfall betrifft, würde ich einfach die gesamte Anfrage nicht bestehen ... aber es hängt wirklich von Ihrem Anwendungsfall ab.
Nathan Phetteplace
3

Dies scheint eine Grauzone der REST-Konvention zu sein.

Ja, bisher bin ich nur auf einen REST-API-Entwurfsleitfaden gestoßen, in dem Stapelvorgänge (z. B. das Löschen von Stapeln) erwähnt werden: den Google API-Entwurfsleitfaden .

In diesem Handbuch erwähnt die Schaffung von „custom“ Methoden , die durch die Verwendung eines Doppelpunktes über eine Ressource zugeordnet werden können, zum Beispiel https://service.name/v1/some/resource/name:customVerb, sie erwähnt auch ausdrücklich Batch - Operationen als Anwendungsfall:

Eine benutzerdefinierte Methode kann einer Ressource, einer Sammlung oder einem Dienst zugeordnet werden. Es kann eine beliebige Anforderung annehmen und eine beliebige Antwort zurückgeben und unterstützt auch Streaming-Anforderungen und -Antworten. [...] Benutzerdefinierte Methoden sollten das HTTP-POST-Verb verwenden, da es die flexibelste Semantik aufweist. [...] Für leistungskritische Methoden kann es hilfreich sein, benutzerdefinierte Stapelmethoden bereitzustellen, um den Overhead pro Anforderung zu reduzieren .

Sie können also laut Googles API-Leitfaden Folgendes tun:

POST /api/path/to/your/collection:batchDelete

... um eine Reihe von Elementen Ihrer Sammlungsressource zu löschen.

B12Toaster
quelle
Ist eine praktikable Lösung, dass die Liste der Elemente über ein JSON-formatiertes Array übertragen wird?
Daniele
ja sicher. Sie können eine Nutzlast POSTEN, in der die IDs über ein JSON-Array gesendet werden.
B12Toaster
Es ist interessant, dass der Google API-Leitfaden If the HTTP verb used for the custom method does not accept an HTTP request body (GET, DELETE), the HTTP configuration of such method must not use the body clause at all,im Kapitel "Benutzerdefinierte Methode" erwähnt wurde. Aber die GET accounts.locations.batchGetAPI ist GET-Methode mit Körper. Das ist komisch. developer.google.com/my-business/reference/rest/v4/…
鄭元傑
@ 鄭元傑 stimme zu, sieht auf den ersten Blick etwas seltsam aus, aber wenn man genau hinschaut, wird tatsächlich eine POSThttp-Methode verwendet und nur die benutzerdefinierte Methode wird benannt batchGet. Ich denke, Google tut es, um (a) an der Regel festzuhalten, dass alle benutzerdefinierten Methoden verwendet werden müssen POST(siehe meine Antwort) und (b) um es den Menschen zu erleichtern, einen "Filter" in den Körper einzufügen, damit Sie dies nicht tun müssen Escape oder Codierung des Filters wie bei Abfragezeichenfolgen. Der Nachteil ist natürlich, dass dies nicht mehr wirklich zwischengespeichert werden kann ...
B12Toaster
https://service.name/v1/some/resource/name:customVerbist per Definition nicht RESTful.
Deamon
2

Ich habe einen umfassenden Ersatz einer Sammlung zugelassen, z. B. PUT ~/people/123/shoeswenn der Körper die gesamte Sammlung darstellt.

Dies funktioniert für kleine untergeordnete Sammlungen von Elementen, bei denen der Client die Elemente überprüfen und einige entfernen und andere hinzufügen und dann den Server aktualisieren möchte. Sie könnten eine leere Sammlung platzieren, um alle zu löschen.

Dies würde bedeuten GET ~/people/123/shoes/9, dass der Cache weiterhin im Cache verbleibt, obwohl er von einem PUT gelöscht wurde. Dies ist jedoch nur ein Caching-Problem und ein Problem, wenn eine andere Person den Schuh löscht.

Meine Daten- / System-APIs verwenden im Gegensatz zu Ablaufzeiten immer ETags, sodass der Server bei jeder Anforderung getroffen wird, und ich benötige korrekte Versions- / Parallelitäts-Header, um die Daten zu mutieren. Für APIs, die schreibgeschützt sind und auf Ansicht / Bericht ausgerichtet sind, verwende ich Ablaufzeiten, um Treffer beim Ursprung zu reduzieren, z. B. kann eine Rangliste 10 Minuten lang gültig sein.

Bei viel größeren Sammlungen, wie z. B. ~/people, muss ich nicht mehrfach löschen, der Anwendungsfall tritt normalerweise nicht auf natürliche Weise auf, sodass ein einzelnes LÖSCHEN einwandfrei funktioniert.

In Zukunft und aufgrund der Erfahrung mit dem Erstellen von REST-APIs und dem Erreichen der gleichen Probleme und Anforderungen wie Audits würde ich gerne nur GET- und POST-Verben verwenden und Ereignisse entwerfen, z. B. POST, ein Ereignis zur Änderung der Adresse, obwohl ich das vermute Ich werde mit seinen eigenen Problemen kommen :)

Ich würde auch Front-End-Entwicklern erlauben, ihre eigenen APIs zu erstellen, die strengere Back-End-APIs verbrauchen, da es oft praktische, gültige clientseitige Gründe gibt, warum sie strenge "Fielding zelot" -REST-API-Designs nicht mögen, und dies für Produktivität und Produktivität Gründe für die Cache-Überlagerung.

Luke Puplett
quelle
Ich habe diese Antwort geliebt, bis ich den letzten Satz gelesen habe :) Ich habe noch nie einen Anwendungsfall gesehen, bei dem die Anwendung von striktem REST einen nachteiligen Nettoeffekt hatte. Sicher, es kann dazu führen, dass an beiden Enden mehr Code geschrieben wird, aber Sie erhalten ein sichereres, saubereres und weniger gekoppeltes System.
Nicholas Shanks
Haha. Es ist tatsächlich ein Muster geworden! Das Backend für das Frontend wird auf dem ThoughtWorks-Technologie-Radar aufgerufen. Es ermöglicht auch das Schreiben von mehr Anwendungslogik, die beispielsweise in JavaScript umständlich wäre und offensichtlich ohne Client aktualisiert werden kann, also beispielsweise für eine iOS-App.
Luke Puplett
Wenn Sie die ersten vier Treffer von Google überfliegen, scheint diese BFF-Technik nur zu funktionieren, wenn die Kunden unter Ihrer Kontrolle stehen . Die Client-Entwickler entwickeln die gewünschte API und ordnen Aufrufe Microservice-APIs zu, die das eigentliche Back-End darstellen. In diesem Diagramm: samnewman.io/patterns/architectural/bff/#bff Ich würde die Zeile "Perimeter" unter den BFF-Feldern platzieren - jedes Feld ist einfach Teil des Clients. Es könnte sogar außerhalb des Rechenzentrums leben, in dem sich die Mikrodienste befinden. Ich sehe auch nicht, wie REST nicht für beide Schnittstellen gilt (Client / BFF und BFF / Microservice).
Nicholas Shanks
1
Ja, das ist ein guter Punkt. Dies ist normalerweise der Fall, wenn Sie beispielsweise ein Team haben, das Microservices erstellt, und ein Team, das eine eckige App erstellt, und dieses Entwicklerteam eher Front-End-Typen sind, die nicht gerne gegen ein paar kleine puristische Dienste arbeiten müssen. Obwohl ich keinen Grund sehe, können Sie nicht dasselbe Muster für die Zusammenfassung von Microservices und die Aggregation zu einer für Ihre Kunden benutzerfreundlicheren Fassade verwenden, sodass die Microservices geändert werden können, ohne die Fassade zu beeinträchtigen.
Luke Puplett
Ein API-Endpunkt sollte die Anforderungen der Domäne und des Unternehmens modellieren. Code zur Lösung dieser Probleme und zur Vermeidung von Überentwicklung, um strenge und oft unflexible Spezifikationen einzuhalten. REST ist sowieso nichts als Richtlinien.
Victorio Berra