2010-06-18 72 views
8

我已經探索了一下,但是當請求成功時我沒有看到HTTP狀態碼,但是在「不返回點」之後有一個錯誤。例如,假設你處理一個請求,它將其提交給數據庫,但在返回結果時你運行內存,或者遇到一個NPE,或者你有什麼。它已經是200響應,但現在,在內部,您無法返回正確,格式良好的響應。「有錯誤成功」的HTTP狀態碼?

202 Accepted似乎不適合,因爲我們已經處理了請求。

什麼狀態碼錶示「成功,但錯誤」?有人甚至存在嗎?

+0

在這種情況下,您必須確定您尚未向客戶端發送一些數據,因爲您已經通過了不返回的要點:在數據的第一個字節之前,標題(包括狀態碼)是發送到瀏覽器。 – 2010-06-18 03:18:59

+0

heh - 授予:)。我想我說的是不可回報之前的不可回報點。不過,大多數情況下,服務器端代碼在發送出去之前在內存中構建完整的響應,因爲它們通常足夠小,可以這樣做。 – 2010-06-18 03:30:50

回答

3

如果服務器知道它遇到了問題,通常應該返回5xx錯誤。最通用的一種是500 Server Error,其RFC 2616定義如下:

500內部服務器錯誤

服務器遇到阻止它 完成請求的意外情況。

然後,客戶有責任重新嘗試請求。如果先前的請求是部分提交的,則服務器(或數據庫)負責將其回滾,或者適當地處理重複的事務。

+1

我對這個答案並不滿意。 「完成」的意思是什麼?我們已經以客戶請求的任何方式修改了資源。如果他們重新加載頁面,他們會看到更改。就用戶而言,它是成功的。對我來說,這聽起來像是我們已經完成了_request_,但還沒有完成_response_。 – 2010-06-18 03:27:48

+0

@Richard:我總是理解「履行」以包括迴應(但我可能在這方面是錯誤的)。儘管如此,這種狀態代碼是非常通用的,只要服務器遇到無法用另一個更具體的5xx錯誤描述的問題,就應該使用它。我認爲[@Jim](http://stackoverflow.com/users/45935/jim-ferrans)描述了我想說的更好,[在其他答案](http://stackoverflow.com/questions/3066972/ HTTP狀態碼換成功與 - 錯誤/ 3067090#3067090)。 – 2010-06-18 04:00:33

1

我同意@Daniel正確的答案是HTTP 500(服務器錯誤)。必須編寫Web應用程序才能在發生錯誤時回滾事務,而不是將事情完成一半。

您可以在Web應用程序中利用的一件事是「冪等性」。這是一個函數(或操作)的屬性,您可以隨意多次重複它,並獲得相同的結果。例如,如果讀取失敗,客戶端可以簡單地重試它直到成功。如果刪除似乎失敗,則客戶端可以再次重試,並且無論被刪除的資源是否已經消失,服務器都會將該請求視爲有效。如果更新失敗,客戶端可以重試,直到它從服務器獲得成功返回。 REST架構Web服務的方法大量使用冪等性,以便在出現錯誤時使操作更加健壯。

+0

爲了澄清,事務已經被提交(例如,考慮在響應的編碼期間發生OutOfMemoryError的情況)。爲了實現冪等性,你需要實現修改控制,不是嗎?讓服務器跟蹤提交的更改和客戶端提供並更改ID。還有處理非臨時性錯誤的情況(比如說有一個導致NPE而不是內存不足錯誤的錯誤) - 客戶可以重試所有他們想要的,但它永遠不會成功(儘管它已經成功第一次,以後的時間是多餘的)。 – 2010-06-22 03:09:27

+0

@理查德:這「一切都依賴」。如果它是一個內容管理應用程序,並且您不介意兩個「同步」更新偶爾會出現嚴格的順序,您不必進行版本控制。但是如果你有更嚴格的約束,版本控制或時間戳可能是合適的。另一種方法是儘可能在交易範圍內形成儘可能多的響應,因此OOME會導致交易中止。也許持久的消息隊列持有事務請求和結果可能是你想要的(查看Apache的ActiveMQ)。 +1的探究問題! – 2010-06-23 06:03:57

4

HTTP沒有這樣的狀態碼,但有一個最佳實踐可以讓你處理這種情況 - 在POST操作後重定向用戶。

這裏是一個擊穿 -

  1. POST請求試圖修改服務器
  2. 如果服務器無法上的數據,它發送一個500錯誤指示失敗
  3. 如果服務器成功,發送302重定向響應
  4. 然後,瀏覽器發送一個新的GET請求到服務器
  5. 如果失敗,你會得到一個500錯誤,否則你會得到一個200

因此,您的'已保存數據但無法立即檢索'的用例轉化爲初始POST的302重定向,隨後爲後續GET獲得500重定向。

這種方法還有其他的優點 - 你擺脫了惱人的'你確定要重新提交數據嗎?'信息。還可以保持後退/前進/刷新按鈕可用。