开发者

How to properly handle an aborted HTTP request in Django

Whenever a lengthy HTTP requests is aborted by the client (e.g. Browser is closed) Django views seem to raise a IOError exception.

What's the proper way to detect such an aborted request if I just want to ignore them? Just 开发者_如何学Gocatching IOError seems too wide.. might accidentally ignore other IO problems.


In django 1.3 and up, you can use a logging filter class to suppress the exceptions which you aren't interested in. Here's the logging filter class I'm using to narrowly suppress IOError exceptions raised from _get_raw_post_data():

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

In Django 1.4, you will be able to do away with most of the complexity and suppress the new exception class UnreadablePostError. (See this patch).


The best way to do it would be to use a custom middleware class that implements process_exception() to return a custom HTTP response, say a rendered errors/request_aborted.html template, if an IOException is caught.


Raven now connects itself to the got_request_exception() signal to catch unhandled exceptions, bypassing the logging system entirely, so the solution proposed by dlowe does not work anymore.

However raven looks for a skip_sentry attribute on the exception instance, so you can use a middleware to set it on the errors you want to ignore:

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

Note: you have to use a recent version of raven (e.g. 1.8.4), as previous versions mistakenly checked for the skip_sentry attribute on the exception type rather than instance.


If you want to ignore the IOError, then just let it be. You don't need to catch it. If you absolutely must catch it, you can do what @Filip Dupanović suggested, and maybe return a django.http.HttpResponseServerError to set the response code to 500.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜