ForceHTTPS Django middleware

Created 13th May, 2008 13:31 (UTC), last edited 13th May, 2008 14:05 (UTC)

This is my first Django middleware and is written as much for me to work out how to do it as because I need it. I suspect that there's already several that do the same thing.

The middleware is intended for use where you want to force all page requests on the site to use HTTPS rather than HTTP. We use it for an intranet and extranet site that sits on the same web server as an ASP.NET application running the public web site. This means that we're also using PyISAPIe to serve the pages and there is a specific workaround because of that. First though the code.

class ForceHTTPS:
    def process_request(self, request):
        if request.META['SERVER_PORT'] == "443" or request.META['HTTP_HOST'] == "localhost:8000":
            return None
        return HttpResponsePermanentRedirect("https://%s%s" % (

There are two implementation specific things that it's worth noting:

  1. Under PyISAPe the request method is_secure() always returns false no matter what. This is why it checks to see if the port number is 443 — standard for HTTPS.
  2. I don't know of a good way to determine if the site is being run using runserver. As this defaults to localhost on port 8000 I check for that instead¹ [1I think putting the port number on the host header is wrong, but still. It isn't something I've ever noticed before and I know that my HTTP client doesn't do it.]

And another note:

  • The middleware assumes that the initial landing on the site is through a GET request. I think anything other than this would be exceptional, but it isn't checked and no exception is thrown. The request will likely fail in some other interesting way once redirected to use HTTPS if another method is tried.

We use this as the first middleware so that no effort is wasted trying anything else before the redirect happens.