2009-09-15 6 views
19

Ich habe eine Ressource, die einen Zähler hat. Aus Gründen der Beispiel wollen wir die Ressource Profil aufrufen, und der Zähler wird die Anzahl der Ansichten für dieses Profil.Inkrementieren Ressourcen-Zähler in einer RESTful Weise: PUT vs POST

Pro REST wiki sollten PUT-Anforderungen für die Erstellung oder Änderung von Ressourcen verwendet werden und sollten idempotent sein. Diese Kombination ist in Ordnung, wenn ich beispielsweise den Namen des Profils aktualisiere, da ich eine PUT-Anfrage ausgeben kann, die den Namen 1000 Mal setzt und das Ergebnis ändert sich nicht.

Für diese Standard PUT-Anfragen, ich habe Browser wie etwas zu tun:

PUT /profiles/123?property=value&property2=value2 

Für einen Zähler erhöht wird, nennt man die URL wie so:

PUT /profiles/123/?counter=views 

Jeder Anruf im Zähler führen inkrementiert werden. Technisch ist es ein Update-Vorgang, aber es verletzt Idempotenz.

Ich bin auf der Suche nach Anleitung/Best Practice. Machst du das nur als POST?

Antwort

8

Eine Alternative könnte darin bestehen, dem System eine weitere Ressource hinzuzufügen, um die Ansichten eines Profils zu verfolgen. Sie könnten es "Anzeigen" nennen.

Um alle Viewings eines Profils zu sehen:

GET/profiles/123/Viewings

ein zu einem Profil sehen hinzu:

POST/Profile/123/Viewings #here, Sie Übermitteln Sie die Details mit einem benutzerdefinierten Medientyp im Anfragetext.

eine vorhandene Viewing aktualisieren:

PUT/Viewings/815 # revidiert Attribute der Anzeigen im Anforderungstext einreichen den benutzerdefinierten Medientyp verwenden Sie erstellt.

Um sich in die Details eines Betrachtungs bohren:

GET/Viewings/815

einen Besichtigungstermin löschen:

DELETE/Viewings/815

Auch, weil Sie‘ Wenn Sie nach Best Practice fragen, stellen Sie sicher, dass Ihr REST-konformes System hypertext-driven ist.

Zum größten Teil ist nichts falsch daran, Abfrageparameter in URIs zu verwenden - geben Sie Ihren Kunden nicht die Idee, dass sie sie manipulieren können.

Erstellen Sie stattdessen einen Medientyp, der die Konzepte verkörpert, die die Parameter zu modellieren versuchen. Geben Sie diesem Medientyp einen prägnanten, eindeutigen und beschreibenden Namen. Dokumentieren Sie dann diesen Medientyp. Das eigentliche Problem beim Aussetzen von Abfrageparametern in REST ist, dass die Praxis häufig zu einer Out-of-Band-Kommunikation führt und daher die Kopplung zwischen Client und Server erhöht.

Dann geben Sie Ihrem System eine einheitliche Schnittstelle. Zum Beispiel ist das Hinzufügen einer neuen Ressource immer ein POST. Das Aktualisieren einer Ressource ist immer ein PUT. Löschen ist DELETE und getting ist GET.

Das Schwierigste an REST ist zu verstehen, wie Medientypen zum Systemdesign passen (es ist auch der Teil, den Fielding aus seiner Dissertation ausgeschlossen hat, weil ihm die Zeit ausgegangen ist). Wenn Sie ein spezifisches Beispiel für ein hypertextgesteuertes System wünschen, das Medientypen verwendet und doubelt, finden Sie unter Sun Cloud API.

+0

Nur um zu verdeutlichen:/viewings/815 bezieht sich auf die 815. Anzeige eines Profils, ja? –

9

Ich denke, die richtige Antwort ist, PATCH zu verwenden. Ich habe niemanden sonst empfiehlt es verwendet werden soll, um atomar einen Zähler zu erhöhen, aber ich glaube, RFC 2068 sagt alles sehr gut:

Die PATCH Methode ähnlich ist, außer zu setzen, die das Unternehmen enthält eine Liste von Unterschiede zwischen der ursprünglichen Version der Ressource , die durch den Request-URI identifiziert wurde, und dem gewünschten Inhalt der Ressource , nachdem die PATCH-Aktion angewendet wurde. Die Liste der Unterschiede ist in einem Format, das durch den Medientyp der Entität definiert ist (z. B. "application/diff") und MUSS ausreichende Informationen enthalten, damit der Server die Änderungen, die zum Konvertieren der ursprünglichen Version des Servers erforderlich sind, erneut erstellen kann Ressource auf die gewünschte Version.

So Profil 123 Ansicht Anzahl zu aktualisieren, würde ich:

PATCH /profiles/123 HTTP/1.1 
Host: www.example.com 
Content-Type: application/x-counters 

views + 1 

Wo der x-counters Medientyp ist (was ich gerade gemacht) aus mehreren Zeilen von field operator scalar Tupeln gemacht. views = 500 oder views - 1 oder views + 3 sind alle syntaktisch gültig (können aber semantisch verboten sein).

Ich kann etwas missverstehen, wenn ich einen anderen Medientyp erfinde, aber ich schlage demütig vor, dass es korrekter ist als die POST/PUT Alternative. Eine Ressource für ein Feld mit einer eigenen URI und vor allem mit eigenen Details (die ich nicht wirklich aufbewahre, sondern nur eine ganze Zahl) zu erstellen, klingt für mich falsch und umständlich. Was ist, wenn ich 23 verschiedene Zähler verwalten muss?

+1

Weicht vom Standard ein kleines Bit ab, da nach der Anwendung der PATCH-Aktion nicht der gewünschte Inhalt der Ressource vorhanden ist. Z.B. Die Entität ist eine Anweisung, die ausgeführt werden soll, nicht das gewünschte Ergebnis. – Pocketsand

+0

Folgt man dem, was @Pocketsand gesagt hat, verstößt dieser Ansatz nicht gegen die Unterbedingung "Manipulation von Ressourcen durch Repräsentationen" unter der Einschränkung "Uniform Interface"? Hier sollten Sie eine Darstellung der Ressource, die Sie sehen möchten, zurücksenden, anstatt Anweisungen zur Manipulation zu senden. – dayuloli

+0

@dayuloli Wenn Sie noch über eine Lösung nachdenken, habe ich [hinzugefügt eine Antwort] (https://stackoverflow.com/questions/1426845/incrementing-resource-counter-in-a-restful-way-put-vs-post/44852115 # 44852115) mit dem, was ich beschlossen habe zu gehen, kann es oder kann Ihren Bedürfnissen entsprechen. – Pocketsand

0

Ich denke, beide Ansätze von Yanic und Rich sind interressant. Ein PATCH muss nicht sicher oder fremd sein, sondern kann robuster gegen Nebenläufigkeit sein. Richs Lösung ist sicherlich einfacher in einer "Standard" -REST-API zu verwenden.

Siehe RFC5789:

PATCH ist weder sicher noch idempotent, wie durch [RFC2616] definiert, Abschnitt 9.1.

A PATCH Anfrage kann in einer solchen Art und Weise ausgestellt werden idempotent, , die hilft auch schlechte Ergebnisse von Kollisionen zwischen zwei PATCH-Anfragen auf die gleiche Ressource in einem ähnlichen Zeitrahmen zu verhindern. Kollisionen von mehreren PATCH-Anforderungen können gefährlicher sein als PUT-Kollisionen, da einige Patch-Formate von einem bekannten Basispunkt aus arbeiten müssen, andernfalls werden sie die Ressource beschädigen.

0

Nach den bisherigen Antworten Auswertung habe ich beschlossen, PATCH für meine Zwecke, das Hantieren mit Content-Type für eine triviale Aufgabe wurde eine Verletzung der KISS principle unangemessen und war. Ich brauchte nur n + 1 so erhöhen ich dies nur tat

PUT /profiles/123$views 
++ 

Wo ++ der Nachrichtentext und wird durch die Steuerung als Befehl interpretiert die Ressource um eins zu erhöhen.

wählte ich $ das Feld/Eigenschaft der Ressource deliminate, da es eine legal sub-delimiter und für meine Zwecke ist, schien intuitiver als /, die, meiner Meinung nach, die Stimmung der Begehbarkeit hat.