2013-07-08 44 views
7

遵循HATEOAS原則,每個州應該超鏈接,建立改變資源狀態的鏈接的最佳方式是什麼?HATEOAS - 如何建模改變狀態的鏈接關係

讓我們用命令經典的例子:

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

我不與「/取消」部分totall快樂 - 我感覺好多了,如果我可以發送「PUT」的要求與內容:

{ 
    status:'cancelled' 
} 

但我怎麼用鏈接部分中的「href」屬性來表示?我想在那裏表示可用的行爲,例如,取消訂單並不總是可能的(「完成」狀態)。

一種可能性就是使用像'/ orders/12?action = cancel'這樣的URL,它有點像RPC方法,我錯過了一些東西。

,看起來可能最好的另一種可能性,是有這樣的鏈接:

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

該解決方案也許感覺有點冗長。

任何想法如何優雅地處理?也許有人已經解決了類似的「問題」?

回答

0

我會建議這兩種模式。第一個是經典之作,但使用rel="edit-form"並使用PATCH。第二種是通過橫向思考HTTP資源模型如何映射到您的應用程序域模型(即,兩者不必具有1:1映射)的替代方案。


解決方案1名

編輯就地資源。兼容

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 

富客戶端(例如HTML +的Javascript)::

HTML兼容

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

status=cancelled 

和/或

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

{ 
    "status": "cancelled" 
} 

_METHOD關鍵是由於HTML的缺乏支持HTTP提供REST框架與正確的方法的公知的手段。


解決方案2

或者,刪除資源(並且,順便說一句,創建一個新的)

DELETE /orders/1 HTTP/1.1 

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

有關這樣的詳細信息將網絡資源映射到域對象,請see my answer到類似的問題。

您可能希望閱讀的另一個答案是this one

8

建模資源是REST中最困難的部分。嚴格遵守標準意味着如果你發現自己曾經這樣做:/resource/:id/{action},你違反了「正確使用HTTP」標準,因爲你的終結點應該始終是「名詞」,而不是「動詞」(動詞是HTTP協議提供)

所以,雖然「這取決於」(即設計資源的最困難的部分),通常爲:。 對象模型狀態可以視爲資源本身

這意味着,您的訂單。 狀態實際上是一個您可以查詢的資源(作爲獨立的/orderstatuses資源或作爲子資源,例如/orders/:id/status

您的應用程序狀態現在可以根據訂單本身的當前狀態鏈接到狀態資源。如果你的「狀態」 模式看起來是這樣的(僞):

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

您的應用可以再PUT /order/:id/status {status:'cancelled'}(井形成狀態)回API,那麼這將採取行動,取消您的訂單。這些術語有點奇怪(RPC更直觀),但希望這會有所幫助。

1

你必須以某種方式描述表格。你「冗長」的解決方案是完全沒有問題:

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

注:你必須定義一個自定義MIME類型或使用一個通用的MIME類型,是能夠描述形式(如集合+ JSON),或一個RDF類型(支持Hydra等REST詞彙) - 又名。統一的接口/自描述消息

我想表示存在可用的操作,因爲例如, 取消命令並不總是可能的(「完成」狀態)。

如果操作不可用,則不要發送指向該操作的鏈接。

0

除了papercowboy的回答,在狀態轉換不總是可用的情況下,您可以記錄當前可能的資源,例如,

/order/:id/availableStates 

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