verwendet einen PUT mit akzeptablen Nebenwirkungen (REST)

9

Ich möchte einen Rückgängig-Verlauf erstellen, wenn der Benutzer ein Formular aktualisiert. Da es sich um ein Update handelt, möchte ich eine PUT-Anforderung verwenden. Ich habe jedoch gelesen, dass PUT keine Nebenwirkungen haben muss .

Ist es akzeptabel, hier PUT zu verwenden? Gibt es bessere Alternativen?

PUT /person/F02E395A235

{
   time: 1234567,
   fields: {
      name: 'John',
      age: '41'
   }
}

Auf dem Server

doPut('person/:personId',
   // create a new person snapshot
)

Bearbeiten:

Der Verlauf ist für den Benutzer sichtbar. Ein mehrmaliger Aufruf würde zu mehreren Versionen führen.

Die Lösung bestand darin, vor dem Erstellen zu überprüfen, ob die Version eindeutig war.

roo2
quelle

Antworten:

10

Die Leute, die HTTP / 2 entwarfen, äußerten sich viel ausführlicher über ihre Ideen, was HTTP tun sollte, während sie die alte Bedeutung beibehielten. Mal sehen, was die HTTP / 2-Entwurfsspezifikation über Idempotenz zu sagen hat:

4.2.2. Idempotente Methoden

Eine Anforderungsmethode wird als "idempotent" betrachtet, wenn die beabsichtigte Auswirkung mehrerer identischer Anforderungen mit dieser Methode auf den Server dieselbe ist wie die Auswirkung einer einzelnen solchen Anforderung. Von den in dieser Spezifikation definierten Anforderungsmethoden sind PUT, DELETE und sichere Anforderung Methoden sind idempotent.

Wie die Definition von safe gilt die idempotente Eigenschaft nur für das, was vom Benutzer angefordert wurde. Es steht einem Server frei, jede Anforderung separat zu protokollieren, einen Revisionskontrollverlauf beizubehalten oder andere nicht idempotente Nebenwirkungen für jede idempotente Anforderung zu implementieren .

Die beabsichtigte Auswirkung auf den Server für jede solche PUT-Anforderung besteht darin, die durch diesen URI identifizierte Ressource zu aktualisieren . Genau das passiert in Ihrem Fall.

Dass Sie sich für die Versionsverwaltung entscheiden, spielt hier keine Rolle. Wenn Sie keine neue Version erstellen möchten, wenn sich nichts geändert hat, müssen Sie die Nutzdaten in der PUT-Anforderung mit der neuesten (oder anderweitig identifizierten) Version der Ressource vergleichen und wenn sich keine der Eigenschaften geändert hat Sie können festlegen, dass keine neue Version erstellt werden soll .


Ihre Bearbeitung:

Der Verlauf ist für den Benutzer sichtbar. Ein mehrmaliger Aufruf würde zu mehreren Versionen führen

Für die Ressource ist dies kein Nebeneffekt . Die Ressource an diesem URI ändert sich nicht (dieselben Eigenschaften erhalten PUT). Der Verlauf besteht nur aus Metadaten, da er höchstwahrscheinlich von einem anderen URI oder mit unterschiedlichen Anforderungsheadern angefordert wird.

CodeCaster
quelle
Ausgenommen, weil Sie mein spezifisches Problem beantworten: "
Ist
Für welches Problem ist das eine Lösung? Dass die timeImmobilie aktualisiert wird? Ich denke, das sind auch Metadaten, obwohl sie in der Ressource enthalten sind.
CodeCaster
1
Das Problem war, dass der Benutzer beim Senden mehrerer PUTs einen langen Rückgängig-Verlauf mit redundanten Informationen erhalten würde. Überprüfung auf Eindeutigkeit löst das
roo2
12

HTTP unterscheidet zwei Eigenschaften:

  • Idempotenz
  • Sicherheit

Die Idempotenz wird durch die Spezifikation wie folgt definiert:

Methoden können auch die Eigenschaft " Idempotenz " haben, da (abgesehen von Fehler- oder Ablaufproblemen) die Nebenwirkungen von N> 0 identischen Anforderungen dieselben sind wie für eine einzelne Anforderung. Die Methoden GET, HEAD, PUTund DELETEdiese Eigenschaft teilen. Außerdem sollten die Methoden OPTIONSund TRACE NICHT Nebenwirkungen haben und sind daher von Natur aus idempotent.

Und Sicherheit:

Insbesondere wurde die Konvention festgelegt, dass die GETund HEADMethoden NICHT die Bedeutung haben sollten, eine andere Aktion als das Abrufen zu ergreifen. Diese Methoden sollten als " sicher " angesehen werden. Auf diese Weise kann Benutzeragenten andere Methoden zur Darstellung, wie POST, PUTund DELETEin einer besonderen Art und Weise, so dass der Anwender der Tatsache bewusst gemacht wird , dass eine möglicherweise gefährliche Aktion angefordert wird.

Natürlich kann nicht sichergestellt werden, dass der Server durch die Ausführung einer GETAnforderung keine Nebenwirkungen erzeugt . In der Tat betrachten einige dynamische Ressourcen dies als eine Funktion. Der wichtige Unterschied besteht darin, dass der Benutzer die Nebenwirkungen nicht angefordert hat und daher nicht für sie zur Rechenschaft gezogen werden kann.

Beachten Sie, dass Sicherheit Idempotenz impliziert: Wenn eine Methode keine Nebenwirkungen hat, führt die mehrfache Durchführung zu derselben Nebenwirkung wie die einmalige Durchführung, nämlich zu keiner.

Dadurch werden die Methoden in drei Kategorien eingeteilt:

  • Safe (und damit auch idempotent): GET, HEAD, OPTION,TRACE
  • idempotent aber nicht unbedingt sicher : PUT,DELETE
  • weder idempotent noch sicher: POST

PUT darf keine Nebenwirkungen haben.

Das ist falsch. PUTist idempotent aber nicht sicher. Der springende Punkt der PUTist , eine Nebenwirkung haben, und zwar auf eine Ressource zu aktualisieren. Was Idempotenz bedeutet, ist, dass das mehrmalige Aktualisieren derselben Ressource mit demselben Inhalt den gleichen Effekt haben sollte wie das nur einmalige Aktualisieren.

Beachten Sie den letzten Absatz im Abschnitt über Sicherheit [Schwerpunkt Mine]:

Natürlich kann nicht sichergestellt werden, dass der Server durch die Ausführung einer GETAnforderung keine Nebenwirkungen erzeugt . In der Tat betrachten einige dynamische Ressourcen dies als eine Funktion. Der wichtige Unterschied besteht darin, dass der Benutzer die Nebenwirkungen nicht angefordert hat und daher nicht für sie zur Rechenschaft gezogen werden kann .

Obwohl dieser Satz über GETund Sicherheit spricht , können wir davon ausgehen, dass die Autoren auch beabsichtigten, dieselbe Argumentation auf PUTund Idempotenz anzuwenden . IOW: PUTsollte nur einen vom Benutzer sichtbaren Nebeneffekt haben, nämlich das Aktualisieren der genannten Ressource. Es kann andere Nebenwirkungen haben, aber der Benutzer kann nicht dafür verantwortlich gemacht werden.

Zum Beispiel bedeutet die Tatsache, dass PUTes idempotent ist, dass ich es so oft wiederholen kann, wie ich möchte: Die Spezifikation garantiert, dass die mehrfache Ausführung genau die gleiche ist wie die einmalige Ausführung. Es ist absolut gültig, einen Rückstand alter Revisionen als Nebeneffekt dieser mehrfachen PUTAnforderungen zu erstellen . Wenn sich Ihre Datenbank jedoch aufgrund mehrerer Wiederholungsversuche mit einem Rückstand alter Revisionen füllt, ist dies nicht mein Problem, sondern Ihr Problem.

IOW: Sie dürfen so viele Nebenwirkungen haben, wie Sie möchten, aber

  1. Es muss für den Benutzer so aussehen, als ob seine Anforderungen idempotent wären
  2. Sie sind für diese Nebenwirkungen verantwortlich, nicht der Benutzer
Jörg W Mittag
quelle
Ja, bei Idempotenz geht es um den Status der Ressource, die gestellt wird, nicht um einen anderen Server- / Dienststatus, der von der PUT-Aktion betroffen ist.
Marjan Venema
Upvote für eine großartige Erklärung der Sicherheit und Idempotenz in Rest
roo2
Tolle Erklärung. Sie machen jedoch mehrere Aussagen wie diese: "Der springende Punkt bei PUT ist, einen Nebeneffekt zu haben, nämlich das Aktualisieren einer Ressource." Das scheint ein Widerspruch zu sein, es sei denn, Sie meinen mit dem Begriff "Nebenwirkung" etwas anderes als "etwas Sekundäres oder Unbeabsichtigtes, das zusätzlich zum primären, beabsichtigten Effekt auftritt".
MarredCheese
@MarredCheese: Ich verwende den Begriff in seiner Standardprogrammierbedeutung, was im Grunde "jedes 'Ergebnis' bedeutet, das nicht der Rückgabewert ist".
Jörg W Mittag
Ah natürlich. Danke für die Klarstellung.
MarredCheese
1

Sie haben Recht, dass PUT keine Nebenwirkungen haben muss , aber ich würde dem etwas hinzufügen.

PUT darf keine Nebenwirkungen auf die Ressource haben, für die diese PUT-Operation ausgeführt wird

Sie aktualisieren eine personRessource, die als gekennzeichnet ist F02E395A235, sodass die Verwendung von PUT korrekt ist. Als Geschäftsregel verfolgen Sie jetzt auch Änderungen, die für die aufrufende Entität (Verbraucher des REST-Service) unsichtbar sind. Dadurch wird der personRessource kein neues Element hinzugefügt . Auf den historischen Schnappschuss kann über den /person/Endpunkt nicht zugegriffen werden. Daher glaube ich, dass PUT in diesem Fall durchaus akzeptabel sein sollte.

Aziz Shaikh
quelle
1
Keine Nebenwirkungen auf die Ressource, aber eine beliebige Anzahl von Nebenwirkungen auf andere Dinge (Zähler, Protokollierung, Prüfspuren, ...) sind durchaus akzeptabel.
Marjan Venema