2013-06-12 109 views
10

我們有一個REST API用於處理應用程序後端。我們需要實現一個衝突預防功能,它會在編輯請求(POST/PUT)中檢查記錄是否在客戶端上次讀取記錄和現在記錄之間未被修改,如果是,則會告訴客戶端存在衝突。編輯衝突和409與412響應

問題是如何發送衝突檢查標記(最可能是一個時間戳,但我們不想強制要求)以及如何返回錯誤。

我們想使用標準的REST模式儘可能的,所以在這裏我們考慮的解決方案:

  • 使用如果-Modified-Since的。這裏的問題是,它強制使用時間戳,規範說你必須返回412.我們想返回更具體的409代碼,以表明它是編輯衝突,as described in the spec,而不是更通用的412,它可以是其他原因造成的。這也會使客戶更容易對編輯衝突進行特殊處理,因爲它們會有專用的錯誤代碼。

  • 使用如果匹配。更好,因爲我們可以使用任何附加的數據,但是規範要求使用412,儘管409更適合我們的情況。此外,規範還建議If-Match鏈接到Etags,並且我們不使用Etags來處理我們的數據,因爲不可能爲每條記錄計算正確的Etag。我們有用於檢查的標籤作爲記錄數據的一部分,但它不會作爲ETag發送,現有客戶端不會處理ETag,因此我們不希望在可能的情況下將這一新要求強加給客戶端。

  • 使用自定義X-Header。這將工作得很好,對客戶來說很容易添加,但如果可能的話,我們更願意使用標準REST手段。

那麼,在這種情況下推薦的方法是什麼?有沒有一種方法可以使用標準的REST方式,用409做出迴應,並讓它一切都很乾淨?

回答

4

基本上,如果你在頭文件中有「If_ *」前提條件,那麼你必須返回412.即使你使用自定義X頭文件,它也只是意味着頭文件沒有定義,它說它必須返回412.如果它是作爲前提條件,如果你看看412定義,你應該返回412來請求X-Header。

This response code allows the client to place preconditions on the current resource metainformation (header field data) ... 

通常ETAG的請求時,纔會發送,猶如─*先決條件的一部分,所以如果你想409,那麼你將無法使用ETAG過。

如果你想使用409,那麼只要把前置條件/​​後置條件放在請求體中而不是頭部。如果條件失敗,Webdav會返回403/409。 409當客戶端可能能夠修復請求。見http://www.ietf.org/rfc/rfc3253.txt

因此,使用412對頭部的先決條件,否則409.

+0

這就是爲什麼我想用409 - 用例正是客戶將獲得新的數據,然後重複用更新的數據的請求。 – StasM

+0

你可以像webdav那樣做。它有自己的頭文件,頭文件中有一個「版本控制」字段。這樣你就不會在http頭中放入任何東西,所以你可以返回409。 – imel96