2013-07-08 13 views
7

Nach HATEOAS Prinzipien, die jeder besagt, sollte Hyperlink sein, was ist der beste Weg, um Links zu modellieren, die Ressource Zustand ändern?HATEOAS - Wie Modell Link-Beziehungen, die den Zustand ändern

Lassen Sie sich klassisches Beispiel mit Aufträgen übernehmen:

{ 
    id : 12, 
    state: 'pending', 
    ..., 
    links: [ 
    ..., 
    { 
     rel: 'cancel', 
     href: '/orders/12/cancel' 
    }, 
    ... 
    ] 
} 

Ich bin nicht totall glücklich mit dieser „/ Abbrechen“ Teil - ich würde viel besser fühlen, wenn ich „PUT“ Anfrage senden konnte mit Inhalt:

{ 
    status:'cancelled' 
} 

Aber wie stelle ich das mit "href" Attribut im Abschnitt Links dar? Ich möchte die verfügbaren Aktionen dort darstellen, da zB das Abbrechen einer Bestellung nicht immer möglich ist (Status 'abgeschlossen').

Eine Möglichkeit wäre, URL wie '/ orders/12? Action = cancel' zu verwenden, wie es sich anfühlt wie RPC-Ansatz und dass mir etwas fehlt.

Eine weitere Möglichkeit, die wahrscheinlich schönsten wäre zu haben Verbindungen wie das aussieht:

{ 
    rel: 'cancel', 
    href: '/orders/12/', 
    type: 'PUT', 
    values: { 
    state: 'cancelled' 
    } 
} 

Diese Lösung fühlt sich vielleicht ein wenig ausführlich.

Irgendwelche Ideen, wie man das anmutig behandelt? Vielleicht hat jemand schon ähnliches "Problem" gelöst?

Antwort

0

Ich würde eines dieser beiden Modelle vorschlagen. Die erste ist die klassische, aber mit rel="edit-form" und PATCH wo verfügbar. Die zweite ist eine Alternative, die durch ein laterales Nachdenken darüber entsteht, wie das HTTP-Ressourcenmodell auf Ihr Anwendungsdomänenmodell abgebildet wird (nämlich, dass die beiden keine 1: 1-Zuordnung haben müssen).


Lösung 1

Bearbeiten der Ressource an Ort und Stelle.

HTML kompatibel:

HTTP/1.1 200 OK 
Content-Type: text/html 
Location: /orders/1/ 

...<a rel="edit-form" href="./edit">Edit</a>... 

HTTP/1.1 200 OK 
Content-Type: text/html 
Location: /orders/1/edit 

... 
<form action="../" method="POST"> 
    <input type="hidden" name="_METHOD" value="PATCH"> 
    <button type="submit" name="status" value="cancelled">Cancel Order</button> 
</form> 
... 

POST /orders/1 HTTP/1.1 
Content-Type: application/x-www-form-urlencoded 

_METHOD=PATCH&status=cancelled 

Rich-Client (zum Beispiel HTML + Javascript) kompatibel:

PATCH /orders/1 HTTP/1.1 
Content-Type: application/x-www-form-urlencoded 

status=cancelled 

und/oder

PATCH /orders/1 HTTP/1.1 
Content-Type: text/json 

{ 
    "status": "cancelled" 
} 

die _METHOD Schlüssel ist ein gut bekanntes Mittel REST-Frameworks mit dem korrekten Verfahren zur Bereitstellung aufgrund HTML Mangel an Unterstützung für HTTP.


Lösung 2

Oder Löschen Sie die Ressource (und, nebenbei bemerkt, eine neue erstellen)

DELETE /orders/1 HTTP/1.1 

HTTP/1.1 201 Created 
Location: /cancelled-orders/1 

Für weitere Informationen über diese Art und Weise der Zuordnung von Webressourcen zu Domänenobjekten, bitte see my answer zu einer ähnlichen Frage.

Eine andere Antwort, die Sie lesen möchten, ist this one.

8

Modellierung von Ressourcen ist der schwierigste Teil von REST. Striktes Befolgen des Standards bedeutet, wenn Sie sich selbst dabei beobachten: /resource/:id/{action}, verletzen Sie die Kriterien "HTTP richtig verwenden", da Ihre Endpunkte idealerweise immer "Substantive", niemals "Verben" sein sollten (die Verben sind das, was HTTP Protokoll zur Verfügung stellt)

so, während „es kommt“ (dh der schwierige Teil Ressourcen der Gestaltung), in der Regel:.. Objektmodellzustände als Ressourcen betrachtet werden können, sich

Was bedeutet, Ihre Bestellung. Status ist eigentlich eine Ressource, die Sie abfragen können (entweder als eigenständige Ressource /orderstatuses oder als Unterressource zB /orders/:id/status)

Ihr Anwendungsstatus kann jetzt basierend auf dem aktuellen Status der Bestellung mit der Statusressource verknüpft werden. Wenn Ihr ‚Status‘ Schema sieht so etwas wie diese (pseudo):

key: 'status' 
values: ['pending', 'cancelled'] 

Ihre Anwendung könnte dann PUT /order/:id/status {status:'cancelled'} (ein gut geformter Status) zurück auf die API, die dann handeln würden Ihre Bestellung stornieren. Es ist etwas komisch, in diesen Begriffen zu denken (RPC ist viel intuitiver), aber hoffentlich hilft das.

1

Sie müssen Formulare irgendwie beschreiben. Sie „ausführliche“ Lösung ist vollkommen in Ordnung:

{ 
    rel: 'cancel', 
    href: '/orders/12/', 
    type: 'PUT', 
    values: { 
    state: 'cancelled' 
    } 
} 

Anmerkung: Sie haben einen benutzerdefinierte MIME-Typen zu definieren, oder einen generischen MIME-Typen verwendet werden, die die Beschreibung Formen fähig ist (zB Sammlung + json), oder welche ein RDF Typ (der REST-Vokabeln wie Hydra unterstützt) - aka. einheitliche Schnittstelle/Selbst beschreibende Nachrichten

ich seit verfügbare Aktionen dort darstellen mag, zum Beispiel eine Bestellung Cancelling ist nicht immer möglich (‚abgeschlossen‘ Zustand).

Wenn eine Operation nicht verfügbar ist, senden Sie keine Verknüpfung, die auf diese Operation verweist.

0

Weiter zu papercowboys Antwort, wo Statusübergänge nicht immer verfügbar sind, können Sie dokumentieren, was derzeit als Ressource möglich ist, z.

/order/:id/availableStates 

{ 
    "availableStates": [ 
     {"status": "cancelled"} 
    ] 
}