Jesper Noehr

Pythonista, RESTafarian, Binary Poet & Proud Bucketeer

HttpOnly with Django

without comments

Did you ever wonder what the dirtiest way to add HttpOnly cookies to Django was, without having to patch both Django and Python?

Well, through the amazing flexibility of the Python language, and the black art of monkeypatching, here’s how:

from Cookie import Morsel
from django.http import HttpResponse

def http_only_cookie(fn):
    def wrap(self, key, *args, **kwargs):
        fn(self, key, *args, **kwargs)
        self.cookies[key]['HTTPOnly'] = True
    return wrap

def exclude(fn, field):
    fields = fn()

    for idx, (k, v) in enumerate(fields):
        if field == k:
            fields.pop(idx)

    return fields

def append_httponly(fn):
    def wrap(self, *args, **kwargs):
        out = fn(self, *args, **kwargs)
        return out+'; HttpOnly'
    return wrap

def bootstrap_httponly():
    HttpResponse.set_cookie = http_only_cookie(HttpResponse.set_cookie)
    Morsel._reserved['httponly'] = 'httponly'
    Morsel.items = lambda self: exclude(super(Morsel, self).items, 'httponly')
    Morsel.OutputString = append_httponly(Morsel.OutputString)

Now just stick this in one of your __init__.py files:

from myapp.httponly import bootstrap_httponly

bootstrap_httponly()

And enjoy cookies like:

Set-Cookie:  sessionid=weirdhash; Domain=.foo.org;
  expires=Fri, 18-Sep-2009 13:18:52 GMT;
  Max-Age=1209600; Path=/; HttpOnly

And that’s that.

Written by jespern

September 4th, 2009 at 2:25 pm

Posted in django, python

Leave a Reply