Jesper Noehr

Pythonista, RESTafarian, Binary Poet & Proud Bucketeer

Conditional middleware execution in Django

without comments

On BitBucket, we need to handle streaming data through Django. This lowers the memory footprint of the application and makes execution faster.

The problem with this is that several stock middleware in Django “look” at the content before sending it. This is a problem for streaming content, since you’d generally use a generator, and you can’t consume it until the very last minute.

The middleware in Django that does this is ConditionalGetMiddleware which attempts to create an ‘ETag’ header, and CommonMiddleware, which attemps to create a ‘Content-Length’ header.

Here’s an easy way of not executing certain middleware in such cases:

def wsgi_compat_middleware_factory(klass):
    class compatwrapper(klass):
        def process_response(self, req, resp):
            if not whatever_condition:
                return klass.process_response(self, req, resp)
            return resp
    return compatwrapper

This is a “factory”, returning a class that can you use instead of the normal middleware. On BitBucket, the condition is ‘if not req.is_mercurial():’. Replace with whatever makes sense for you.

You use it by doing something like this:

from django.middleware.http import ConditionalGetMiddleware
from django.middleware.common import CommonMiddleware

StreamingConditionalGetMiddleware = wsgi_compat_middleware_factory(ConditionalGetMiddleware)
StreamingCommonMiddleware = wsgi_compat_middleware_factory(CommonMiddleware)

Now you have two new classes – Just install those in place of the stock middleware, and viola.

Written by jespern

January 20th, 2009 at 8:32 am

Posted in django, python

Leave a Reply