When I put together the ForceHTTPS Django middleware there was an annoying and not very good work around for a bug between PyISAPIe and Django. The problem was that
django.http.Request.is_secure() would always return False — not helpful. Since then I've more or less ignored it hoping that it would go away, but today I tracked down Selenium test failures for Internet Explorer to the same cause so had to come up with a fix. Thankfully it wasn't too hard.
Django uses the following implementation of
def is_secure(self): return os.environ.get("HTTPS") == "on"
The problem is that this doesn't work on Windows because it doesn't set an environment variable for this — it sets a server variable which PyISAPIe should expose under
Request.META. The problem there is that the HTTPS server variable is missing from PyISAPIe's code.
django.core.handlers.pyisapie._get_meta() needs to have HTTPS added to the list of names it forwards:
'CONTENT_TYPE': Env.CONTENT_TYPE, 'HTTPS': Env.HTTPS, # Add this line 'GATEWAY_INTERFACE': Env.GATEWAY_INTERFACE,
The best fix for the Django side of things isn't quite so obvious. The code i went for was this:
def is_secure(self): environ = os.environ.get("HTTPS") if environ: return environ == "on" return self.META.get("HTTPS").lower() == "on"
There are plenty of other ways to skin this cat too depending on what you're trading off. I'm assuming that you don't want too many lookups into the environment Dict and that most Django users will be running on some platform where
os.environ.get("HTTPS") will work as expected. I'm not certain if the case conversion is required or not.