2016-08-09 18 views
2

每個用戶都有一個寶石集合。這些寶石可以通過REST API來訪問:REST - ETag在POST到資源收集和If-Match標頭時

GET /user/<user id>/gem    -> get all gems 
GET /user/<user id>/gem/<gem id>  -> get an existing gem 
POST /user/<user id>/gem    -> add a new gem 
PUT /user/<user id>/gem/<gem id>  -> edit an existing gem 
DELETE /user/<user id>/gem/<gem id>  -> delete an existing gem 

我有幾個後端進程,這同時運行,並可能通過POST HTTP方法添加寶石。 (他們也可以編輯(PUT)或刪除(DELETE)寶石,但這對我的問題並不重要,實際上是這樣,請繼續閱讀。)

從高層次看,他們做了以下:

1. GET /user/<current user id>/gem 
2. some calculations, based on step 1 
3a. if (step 2 decided that a gem should be added) 
3b.  POST /user/<current user id>/gem 

如前所述,這些過程並行運行。通常,兩個進程不管理同一用戶的寶石,但可能會發生。

所以我需要一種機制,在步驟3b中禁止POST,如果在此期間有所改變。我想過使用ETags和樂觀鎖定:

1. GET /user/<current user id>/gem and remember the returned ETag 
2. some calculations, based on step 1 
3a. if (step 2 decided that a gem should be added) 
3b.  POST /user/<current user id>/gem with header 'If-Match=<ETag from step 1>' 
3c.  if (server returns 412 - precondition failed) 
3d.   start again at step 1 

我不確定ETag是否適用於此目的。 ETag的大多數示例都是關於一個資源(如/gem/23),但不是關於資源集合(如/gem)。也就是說,在步驟3b中,我提供了完整寶石集合的ETag,而本質上我提供了一個要添加的寶石。

回答

0

當然,你的問題聽起來像是非常適合ETags的使用。它是一個集合的事實並不重要;重要的是它是一個具有代表性的資源,可以始終從中生成ETag。

需要考慮的一件事是,如果有關於集合表示的任何事情可以改變,那麼這與API消費者無關。例如,假設您以某種隨機或不一致的順序輸出集合,但集合在語義上定義爲無序。在這種情況下,您可以根據集合中的一組項目生成weak ETag

+0

謝謝你在這裏使用弱ETag的提醒! –