[Django]-How to properly handle an aborted HTTP request in Django

2👍

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).

👤dlowe

1👍

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.

1👍

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.

0👍

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.

Leave a comment