2014-01-18 25 views
5

我正在開發一個在線遊戲,角色可以對其他對象和角色執行復雜的動作。我正在構建一個REST API,並且在嘗試遵循一些最基本的標準時遇到了很多麻煩。我知道REST並不總是答案,但出於各種原因,我認爲使用REST是合理的,因爲API的其餘部分正確使用它。您如何爲REST中的複雜操作建模?

下面是一些例子棘手:

GET /字符/鮑勃/項目 這將返回鮑勃攜帶物品的陣列。

我需要針對這些項目執行各種「操作」,並且即時將此模型設置爲「資源」非常困難。

這裏有一些可能採取的行動,這取決於項目的性質: 扔,吃,掛斷,保留

這是複雜的,因爲這些「操作」只適用於某些項目。例如,你不能吃劍。而且,「吃飯」本質上具有「刪除」資源的副作用。使用'throw'也可以'刪除'資源。使用'drop'可能會將資源'轉換'爲另一種資源類型。 '投擲'要求我提供'位置'。 'Hold'需要我提供哪隻手來放置物品。那麼如何將這些操作建模爲資源?他們都不相似,因爲他們每個人都需要不同的參數,導致完全不同的行爲。

目前,我有一個「動作」資源,我張貼這些任意行動。但這種感覺太RPC和非標準化的/可發現:

POST /動作/投擲 { 或CharacterId:5, 的itemId:10, X:100, Y:150 }

回答

6

我儘可能地堅持資源和GET/POST/PUT/PATCH/DELETE,但基礎動詞往往直接映射到CRUD調用。其他更復雜的操作通常無法在沒有附加信息的情況下進行映射。

着眼於資源,我可能會做這樣的事情(發佈消息的資源):

POST /characters/bob/items/{bombId}?action=throw 
POST /characters/bob/items/{foodId}?action=eat 
POST /characters/bob/items/{potionId}?action=add&addedItem={ingredientId} 

返回一個錯誤的時候,動作是不適合的項目。

+0

我不太確定我瞭解這種方法。用這種類型的POST修改什麼'狀態'/'表示'/'資源'?這感覺像RPC,因爲查詢參數最終決定了預期POST的「模式」。 – user43823

+1

您的資源是正在使用的對象(這是您正在修改的對象)。不要將動作參數視爲查詢 - 我認爲它是替代動詞。 HTTP/REST不提供動詞EAT,但action = eat正在嘗試對其進行建模。我認爲複雜的多資源消息很難模擬。我會說「POST/actions/throw」對我來說似乎更像RPC。 –

+0

@MikeDunker:你可以用'{item:X}'創建資源(集合)'meals' /'eatings'和'POST'新項目到',即:'POST/characters/bob/eatings'' 。或者你可以用'{name:'eat',item:X}'創建更通用的'operations'資源,然後'POST/characters/bob/operations'。 – marcinn

1

我希望資源在保持REST風格的同時「做一個複雜的動作」,我會將一個複雜的文檔發佈到描述我想要發生的事情的資源上。 (複雜文檔可以是XML,JSON或任何其他格式。)這與將POST映射到「創建子資源」的更常見模式有所不同,但POST的含義是「do non-冪等由身體內容定義的動作「。這對你所追求的是合理的。

作爲HATEOAS發現原理的一部分,當您獲取稍後發佈的資源時,返回的文檔的一部分應該說明這些複雜的動作文檔是什麼以及它們應該發送到哪裏。從邏輯上講,可以考慮填寫表單並提交它(即使「表單」實際上是插入JSON文檔或類似的東西)。