2011-08-14 65 views
2

只要客戶端中止了長時間的HTTP請求(例如,瀏覽器關閉),Django視圖似乎會引發IOError異常。如何在Django中正確處理異常終止的HTTP請求

如果我只是想忽略它們,檢測這種中止請求的正確方法是什麼?只是捕捉IOError似乎太寬..可能會意外忽略其他IO問題。

回答

1

做到這一點的最佳方法是使用實​​現process_exception()的自定義中間件類來返回自定義HTTP響應,例如,如果捕獲到IOException,則返回errors/request_aborted.html模板。

+0

但是如果拋出其他一些IOError,而不是因爲中止而出於某種其他原因呢?然後,我會壓制這個錯誤... –

+0

這適用於未捕獲的異常。通常,當您執行IO操作時,您將嘗試捕獲所有可能的異常,以確保只有中止的請求未被捕獲。 –

+0

但是,知道IOError來自何處並不那麼容易。例如。我經常通過訪問request.POST來看到它。我需要一種方式來區分客戶端與其他類型的IO錯誤,並假設幾乎所有框架函數都可以引發IOError。 –

0

如果您想忽略IOError,那就讓它成爲。你不需要抓住它。如果你絕對必須抓住它,你可以做@FilipDupanović建議的,並且可能會返回一個django.http.HttpResponseServerError來將響應代碼設置爲500

+1

我不想讓它成爲因爲我記錄所有未被捕獲的錯誤,並且這會產生日誌噪音。 –

2

在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)。

1

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屬性。