2013-03-22 47 views
6

我只花了20分鐘調試一些(Django)單元測試。我正在測試一個視圖POST,並且我期待着一個302返回代碼,在此之後,我聲稱一堆數據庫實體如預期的那樣。原來最近合併的提交已經添加了一個新的表單字段,並且我的測試失敗了,因爲我沒有包含正確的表單數據。我應該使用HTTP 4xx來表示HTML表單錯誤嗎?

問題是測試失敗,因爲HTTP返回代碼是200,而不是302,我只能通過打印響應HTTP並查看它來解決問題。除了需要查看HTML來解決問題之外,200看起來像一個POST沒有得到處理的錯誤代碼。 4xx(客戶端錯誤)似乎更合適。另外,它會使調試測試變得簡單,因爲響應代碼會直接指出我的問題。

我已閱讀有關使用422(不可處理的實體)作爲REST API中可能的返回碼,但無法在HTML視圖/處理程序中找到任何使用它的證據。

我的問題是 - 是否有其他人這樣做,如果沒有,爲什麼不呢?

[UPDATE 1]

只是爲了澄清,這個問題涉及到HTML表格,而不是一個API。

這也是一個關於HTTP響應代碼本身的問題 - 不是Django。這恰好是我正在使用的。我已經刪除了django標籤。

[UPDATE 2]

一些進一步澄清,以W3C的引用(http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html):

10.2成功的2xx

這類狀態代碼表示該客戶機的請求被成功地接受,理解和接受。

10.4客戶端錯誤4XX

的4XX類的狀態代碼是用於在客戶端似乎有錯誤的案件。

10.4.1 400錯誤的請求

請求不能被服務器因爲語法錯誤的理解。

而且從https://tools.ietf.org/html/rfc4918#page-78

11.2。 422無法處理的實體

的422(無法處理的實體)狀態代碼表示該服務器 理解請求實體(因此一個 415(不支持的媒體類型)狀態代碼是不適當的)的內容類型,和的所述 語法請求實體是否正確(因此400(錯誤請求) 狀態碼不合適),但無法處理包含的 指令。例如,如果XML 請求主體包含格式正確(即語法正確),但是語義錯誤的XML指令 ,則可能會出現此錯誤情況。

[UPDATE 3]

掘到它,422是一個WebDAV擴展[1],這可以解釋它的模糊。也就是說,由於Twitter使用420用於他們自己的目的,我想我會隨心所欲。但它會與一個4.

[UPDATE 4]

註釋開始於使用定製響應代碼,以及應如何被處理(如果未識別)中,從HTTP 1.1規範(http://tools.ietf.org/html/rfc2616#section-6.1.1):

HTTP狀態碼是可擴展的。 HTTP應用程序不需要 來理解所有註冊狀態代碼的含義,雖然這樣的理解顯然是可取的。但是,應用程序必須瞭解任何狀態代碼的類別(如第一個 數字所示),並將任何未識別的響應視爲等同於該類別的 x00狀態代碼,但不應將無法識別的響應緩存。例如,如果客戶端接收到一個 無法識別的狀態碼431,則它可以安全地假定其請求出現問題,並且 將該響應視爲已收到400狀態碼。在這種情況下,用戶代理應該向用戶呈現帶有響應的返回 的實體,因爲該實體可能包括可解釋異常狀態的可讀信息。

[1] https://tools.ietf.org/html/rfc4918

+1

這真的取決於您決定如何設計您的API。我不確定422是最好的響應代碼,但是可以確定的是,您可以在4xx範圍內發送除200之外的其他內容。 – 2013-03-22 22:45:51

+0

@MattBall出於興趣 - 你爲什麼不認爲這是最好的代碼? (我也沒有答案 - 但是以4開頭的東西比2更好)? – 2013-03-22 23:05:26

+0

不直接回答你的問題,但http://stackoverflow.com/q/1959947/139010。 – 2013-03-22 23:11:58

回答

1

你是對的,如果結果不成功,200是錯誤的。

我還認爲,一個成功的,具有重定向到結果頁應該是303,而不是302

4XX是客戶端錯誤是正確的。 422對我來說似乎是對的。無論如何,不​​要通過IANA註冊新的4xx代碼。

+0

我對422的保留只是它不是原來的W3C規範,而是一個WebDAV擴展。我選擇421的原因是422是最接近的現有代碼,420是Twitter的編寫代碼,因此它們之間的中間部分似乎是合適的。 – 2013-03-27 16:41:27

+0

另外 - 雖然我得到了「不要發明自己的」情緒 - 實際上最糟糕的情況是什麼(這是一個真正的問題,我沒有挑釁性)。 – 2013-03-27 16:43:06

+0

a)HTTP/1.1是IETF規範,而不是W3C規範 b)規範沒有列出所有狀態代碼,在http://www.iana.org/assignments/http-status-代碼/ http-status-codes.xml c)定義在WebDAV規範中的事實是不相關的; 422是通用狀態碼。 d)最糟糕的情況是,其他人定義421,使其受到歡迎,其定義與您的定義相沖突。它只是發生在谷歌身份代碼308,順便說一句。 – 2013-03-27 17:00:28

-1

的POST返回200,如果你不重定向。 在POST請求後,302不會自動發送到標題中,因此您必須手動發送標題(https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpResponse),並且代碼不會在表單的數據上進行中繼。

使用代碼302重定向回到表單(或其他)的原因是禁止瀏覽器在刷新或歷史瀏覽時重複發送數據。

+2

這是一個關於HTTP的問題。我知道django是如何工作的。 – 2013-03-22 23:09:02

1

似乎沒有被接受的答案,說實話,有點令人驚訝。表單驗證是Web開發的基石,因此沒有響應代碼來說明驗證失敗,這看起來像是錯失了機會。特別是考慮到自動化測試的擴散。通過檢查錯誤消息的HTML內容來測試響應似乎並不實際,而不僅僅是測試響應代碼。

我堅持我的斷言在這個問題中,200是一個錯誤的響應代碼,對於一個不符合業務規則的請求 - 那302也是不合適的。 (如果表單驗證失敗,那麼它不應該更新服務器上的任何狀態,因此是冪等的,並且不需要使用PRG模式來阻止用戶重新提交表單。讓他們)

所以,鑑於沒有「批准」方法,我目前正在測試(字面意義上的)我自己的 - 421.如果遇到使用非標準HTTP狀態代碼的任何問題,我會報告回來。

如果這個答案沒有更新,那麼我們正在使用它在生產中,它的工作原理,你可以做同樣的事情。

0

很明顯,某些表單POST請求會導致4xx HTTP錯誤(例如,錯誤的URL,缺少預期的字段,無法發送auth cookie),但是忘記密碼或意外省略必需字段是非常常見和預期的事件在應用程序中。

從任何規範中看不出每個表單失效問題都必須構成HTTP錯誤。

我想我的直覺是,如果服務器向客戶端發送一個表單,並且客戶機以正確形式的POST請求對所有期望的字段進行了形式正確的POST請求回覆,那麼通常的業務邏輯違規不應該是HTTP錯誤。

如果客戶端腳本使用HTTP作爲傳輸機制,情況似乎更加不明確。例如。如果JSON-RPC請求發送表單詳細信息,則服務器端函數被成功調用並且返回給調用者的響應看起來像是200次成功。

有趣的是:使用錯誤憑據登錄會從Facebook,Google和維基百科獲得200,亞馬遜獲得204。

理想情況下,IETF會用RFC清除它,可能會添加一個HTTP錯誤代碼,用於「由於表單失效失敗而未執行操作」或擴展422的定義以涵蓋此操作。

相關問題