Wir haben eine URL im folgenden Format
/ instance / {instanceType} / {instanceId}
Sie können es mit den Standard-HTTP-Methoden aufrufen: POST, GET, DELETE, PUT. Es gibt jedoch noch einige weitere Aktionen, die wir durchführen, z. B. "Als Entwurf speichern" oder "Kuratieren".
Wir dachten, wir könnten einfach benutzerdefinierte HTTP-Methoden verwenden, wie ENTWURF, GÜLTIG, KURAT
Ich denke, das ist akzeptabel, da die Standards sagen
"Der Satz allgemeiner Methoden für HTTP / 1.1 wird nachstehend definiert. Obwohl dieser Satz erweitert werden kann, kann nicht davon ausgegangen werden, dass zusätzliche Methoden dieselbe Semantik für separat erweiterte Clients und Server verwenden."
Und Tools wie WebDav erstellen einige ihrer eigenen Erweiterungen.
Gibt es Probleme mit benutzerdefinierten Methoden? Ich denke an Proxy-Server und Firewalls, aber auch andere Bereiche sind willkommen. Sollte ich auf der sicheren Seite bleiben und nur einen URL-Parameter wie action = validate | curate | draft haben?
Antworten:
Eine der grundlegenden Einschränkungen von HTTP und der zentralen Entwurfsfunktion von REST ist eine einheitliche Schnittstelle, die unter anderem von einer kleinen, festen Gruppe von Methoden bereitgestellt wird, die universell für alle Ressourcen gelten. Die einheitliche Schnittstellenbeschränkung weist eine Reihe von Vor- und Nachteilen auf. Ich zitiere hier großzügig aus Fielding .
Eine einheitliche Schnittstelle:
Zum anderen eine einheitliche Oberfläche:
Die Kompromisse sind "für den allgemeinen Fall des Webs ausgelegt" und haben den Aufbau eines großen Ökosystems ermöglicht, das Lösungen für viele der allgemeinen Probleme in Webarchitekturen bietet. Das Festhalten an einer einheitlichen Schnittstelle ermöglicht es Ihrem System, von diesem Ökosystem zu profitieren, während ein Bruch es so schwierig macht. Möglicherweise möchten Sie einen Load Balancer wie nginx verwenden, aber jetzt können Sie nur einen Load Balancer verwenden, der DRAFT und CURATE versteht. Möglicherweise möchten Sie eine HTTP-Cache-Ebene wie Varnish verwenden, aber jetzt können Sie nur eine HTTP-Cache-Ebene verwenden, die DRAFT und CURATE versteht. Möglicherweise möchten Sie jemanden um Hilfe bei der Behebung eines Serverfehlers bitten, aber niemand kennt die Semantik für eine CURATE-Anforderung. Es kann schwierig sein, Ihre bevorzugten Client- oder Server-Bibliotheken zu ändern, um die neuen Methoden zu verstehen und korrekt zu implementieren. Und so weiter.
Die korrekte Darstellung * erfolgt als Statusumwandlung für die Ressource (oder verwandte Ressourcen). Sie ENTWURFEN keinen Beitrag, Sie transformieren seinen
draft
Status intrue
oder Sie erstellen einedraft
Ressource, die die Änderungen und Links zu früheren Entwurfsversionen enthält. Sie KURIEREN einen Beitrag nicht, Sie wandeln seinencurated
Status intrue
einecuration
Ressource um oder erstellen eine Ressource, die den Beitrag mit dem Benutzer verknüpft, der ihn kuratiert hat.* Richtig, da es den REST-Architekturprinzipien am nächsten kommt.
quelle
Ich würde es vorziehen, diese als Subressourcen zu gestalten, für die Sie eine POST-Anfrage durchführen.
Angenommen, Sie haben eine Ressource unter
/instance/type/1
, dann würde die Darstellung dieser Ressource einige Links zu "Aktionen" enthalten, die für die Ressource ausgeführt werden können, z. B./instance/type/1/draft
und/instance/type/1/curate
. In JSON könnte dies so einfach sein:Auf diese Weise kann der Client während der POST-Anforderung an den vom
curate
Mitglied bereitgestellten Link sehr genau angeben, was zu tun ist . Die dort veröffentlichte Ressource könnte Argumente enthalten, die das Ereignis detailliert beschreiben, das möglicherweise einen Zustandsübergang verursachen würde.Die "naive" Herangehensweise, zwischen den möglichen Zuständen einer Ressource zu wechseln, hat den Nachteil, nicht zu erfassen, welche Ereignisse zu diesen Übergängen geführt haben.
Zustandsübergänge treten normalerweise als Reaktion auf bestimmte Ereignisse auf, und ich möchte diese Ereignisse lieber erfassen, als den Client entscheiden zu lassen, dass sich etwas in einem bestimmten "Zustand" befindet. Dies erschwert auch die Validierung erheblich. Außerdem könnten Sie keine „Argumente“ erfassen, wenn Sie nicht auch die im Staat selbst beschreiben. Und dann wird es icky, wenn ein Code diejenigen ohne echten Zustandsübergang ändert und die erforderliche Validierung und das Ganze schnell zu einem Chaos wird.
quelle
/vms/some-id
gibt Links zu Aktionen wie zurückPOST /vms/some-id/restart
und wir bestimmen damit, ob Aktionen aktiviert oder deaktiviert werden sollen. Ich habe eine Hassliebe zu HATEOAS :)Ich denke, benutzerdefinierte HTTP-Methode ist der beste Weg, um Entity-Aktionen zu implementieren. Das Hinzufügen der Aktion zum Entitätshauptteil (POST) scheint nicht richtig zu sein, da es nicht zu Ihrer Entität gehört (obwohl das Ergebnis möglicherweise darin gespeichert wird). Mithilfe der benutzerdefinierten HTTP-Methoden können Proxys auch ihre Aktionen bestimmen, ohne dass der Entitätskörper analysiert werden muss.
Es ist wie bei CRUD, Sie würden diese immer implementieren wollen, aber Sie haben auch Ihre eigenen spezifischen Aktionen (je nach Aktivität). Ich verstehe wirklich nicht, was das Problem wäre, diese zu erweitern.
Auch @Rein Henrichs "Sie ENTWURFEN keinen Beitrag, Sie wandeln seinen Entwurfsstatus in" true "um oder Sie erstellen einen Entwurf für eine Ressource" scheint mir falsch zu sein. Eine
drafts
Eigenschaft wird zum dauerhaften Speichern des Zustands und nicht zum Durchführen der Umwandlung verwendet. Aktionen führen nicht unbedingt zu einem 'Zustand' oder werden in einer Eigenschaft gespeichert. Das Erstellen einer separaten Entität für jeden Zustand / jede Transformation scheint noch unscharfer zu sein. Versuchen Sie, den gleichen Verweis (URI) auf die Einheit beizubehalten.quelle