Conditional middleware execution in Django
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.
