只要客戶端中止了長時間的HTTP請求(例如,瀏覽器關閉),Django視圖似乎會引發IOError異常。如何在Django中正確處理異常終止的HTTP請求
如果我只是想忽略它們,檢測這種中止請求的正確方法是什麼?只是捕捉IOError似乎太寬..可能會意外忽略其他IO問題。
只要客戶端中止了長時間的HTTP請求(例如,瀏覽器關閉),Django視圖似乎會引發IOError異常。如何在Django中正確處理異常終止的HTTP請求
如果我只是想忽略它們,檢測這種中止請求的正確方法是什麼?只是捕捉IOError似乎太寬..可能會意外忽略其他IO問題。
做到這一點的最佳方法是使用實現process_exception()
的自定義中間件類來返回自定義HTTP響應,例如,如果捕獲到IOException
,則返回errors/request_aborted.html
模板。
如果您想忽略IOError
,那就讓它成爲。你不需要抓住它。如果你絕對必須抓住它,你可以做@FilipDupanović建議的,並且可能會返回一個django.http.HttpResponseServerError
來將響應代碼設置爲500
。
我不想讓它成爲因爲我記錄所有未被捕獲的錯誤,並且這會產生日誌噪音。 –
在Django 1.3及以上,你可以使用一個logging filter類壓制你不感興趣的例外下面是我使用狹義抑制來自_get_raw_post_data()
引發的IOError異常日誌過濾器類:
import sys, traceback
class _SuppressUnreadablePost(object):
def filter(self, record):
_, exception, tb = sys.exc_info()
if isinstance(exception, IOError):
for _, _, function, _ in traceback.extract_tb(tb):
if function == '_get_raw_post_data':
return False
return True
在Django 1.4中,您將能夠消除大部分複雜性並抑制新的異常類UnreadablePostError
。 (見this patch)。
Raven現在將自己連接到got_request_exception()信號以捕捉未處理的異常,完全繞過日誌系統,因此dlowe提出的解決方案不再有效。
但是烏鴉查找該異常實例skip_sentry
屬性,所以你可以使用一箇中間件來設置它的錯誤,你要忽略:
import sys
import traceback
class FilterPostErrorsMiddleware(object):
"""
A middleware that prevents unreadable POST errors to reach Sentry.
"""
def process_exception(self, request, exception):
if isinstance(exception, IOError):
tb = sys.exc_info()[2]
for _, _, function, _ in traceback.extract_tb(tb):
if function == '_get_raw_post_data':
exception.skip_sentry = True
break
注意:你必須使用一個最近版本的烏鴉(例如1.8.4),因爲以前的版本在異常類型而不是實例上錯誤地檢查了skip_sentry
屬性。
但是如果拋出其他一些IOError,而不是因爲中止而出於某種其他原因呢?然後,我會壓制這個錯誤... –
這適用於未捕獲的異常。通常,當您執行IO操作時,您將嘗試捕獲所有可能的異常,以確保只有中止的請求未被捕獲。 –
但是,知道IOError來自何處並不那麼容易。例如。我經常通過訪問request.POST來看到它。我需要一種方式來區分客戶端與其他類型的IO錯誤,並假設幾乎所有框架函數都可以引發IOError。 –