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" % (
request.META['HTTP_HOST'].split(':')[0],
request.get_full_path(),
))
There are two implementation specific things that it's worth noting:
is_secure()
always returns false no matter what. This is why it checks to see if the port number is 443 — standard for HTTPS.manage.py 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:
We use this as the first middleware so that no effort is wasted trying anything else before the redirect happens.