2011-06-05 20 views
3

假設我有兩個實體 - 項目團隊和員工。每個員工可以是多個團隊的一部分,每個團隊可以有多個員工作爲團隊成員。我需要提供REST API來操縱團隊,員工和他們之間的關係。在不影響REST中子資源的情況下更新資源的正確HTTP方法

我確定了3個資源 - 團隊,員工和成員(團隊和員工之間的關聯),這是團隊的子資源。我選擇將會員作爲子資源的原因純粹是基於此資源的生命週期。每當團隊被移除時,成員被移除,以及他們在團隊本身之外沒有意義。

我露出下面的API(相關的):

  • POST /teams創建了名新球隊戰績,部門ID等
  • POST /teams/{name}/members創建名稱和特定僱員鑑定團隊之間的關聯,所以輸入數據包含員工ID

我還需要提供API以在一個請求中更新部門ID和團隊的其他屬性。看起來PUT是自然選擇,但PUT的語義非常清晰 - 我必須替換整個資源,在這種情況下,這意味着要替換所有成員子資源。

當我只想在保留成員關聯的同時更新團隊屬性時,應該使用什麼方法(或方法)?請記住,我也希望這個請求是冪等的。

回答

5

貌似PUT是很自然的選擇,但PUT的 語義是相當清楚的 - 我 不得不更換整個資源,這 在這種情況下,意味着更換所有 成員子資源也是如此。

我從來沒有聽說過任何人做過這種關聯。如果在我看來PUT /Foo/Foo/bar完全沒有說。僅僅因爲可以通過分層URI空間訪問資源,並不能推斷這些資源之間的任何附加關係。

我聽說有人在做,你做PUT /Foo/bar,如果服務器知道,這將影響/Foo狀態可以包含指向/Foo允許智能高速緩存無效/Foo一個Content-Location頭相反的情況。但是,Content-Location需要明確地創建兩個資源之間的關係。

+0

這是非常好的一點。我想你是對的,我認爲URI是一組資源的嚴格樹形表示。相反,我應該將它們看作只是一種識別方式,其中嵌套意味着指定命名空間。順便說一句,如果我遵循這個假設,GET的反應將如何看起來像一個「團隊」?返回正文中成員的URI是否是好事,或者我應該只返回團隊的屬性而忽略成員?也許包括像「/ teams/123/members」這樣的URI是一種方式嗎? – 2011-06-06 02:58:11

+0

@Oleg我會在你的團隊代表中包含一個指向'/ teams/123/members'的鏈接。 – 2011-06-06 12:29:32

+0

謝謝,我需要一個更多的澄清,請在對'/ teams/123'進行PUT時忽略包含'/ teams/123/members'到請求主體的鏈接是好主意,否則這會混淆客戶端? – 2011-06-06 13:15:34

2

理想情況下,您應該使用PATCH方法,但不確定哪個實現使用它。如果沒有,你應該直接GET - >本地修改 - > PUT週期。

此外,根據您的設計,您可能會認爲子資源不屬於資源本身。例如,團隊資源的內容可能包含指向資源成員列表的鏈接,如「/team/{name}/members」,但不包含整個列表作爲包含的元素。

+0

問題在於使用GET-> modify-> PUT會使服務器上的邏輯顯着複雜化。它必須確定哪些關聯發生了變化並適當地執行後端操作。我寧願在方法和主體中傳達僅更新團隊屬性的意圖。 – 2011-06-05 23:25:07

+1

另一方面,不把會員作爲單獨的資源處理可能是一個好主意。因此,如果有人想獲得成員名單,它將不得不發出單獨的請求,而對於「團隊」URI的POST/PUT將始終只處理團隊屬性 – 2011-06-05 23:27:23

-2

我覺得你在回答你自己的問題。 PUT建議創建資源POST用於更新。

另一種看待這個問題的方式是,對資源的每一次更改都是真正「創建新版本」的資源。每創建,更新和刪除都添加一個新版本和新屬性,並且版本具有其自己的唯一標識符。如果PUT是現有資源的新版本,則舊資源將保留,以便新資源可以繼承它。嘗試在舊版本上嘗試PUT新版本時,如果該資源的較新版本已經存在,將返回重定向而不是成功,所以會有一些GET請求(並不表示它們實際上正在查找舊版本)