HTTPS with django and WSGI
This works almost fine, except sometime views fall into infinitive loop with redirect http->https->http->https. This make me nervous, so to save solution how to make this 2 scripts work together:
#SSl middleware
#ssl.py
#original — http://www.djangosnippets.org/snippets/240/
#use {'SSL':True} for the urls which should be redirected to https
from django.conf import settings
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect, get_host
import django.contrib.auth.decorators
import os
SSL = 'SSL'
def is_secure(request):
if 'HTTPS' in request.META:
return request.META['HTTPS'] == 'on'
return False
class SSLRedirect:
def process_view(self, request, view_func, view_args, view_kwargs):
if SSL in view_kwargs:
secure = view_kwargs[SSL]
del view_kwargs[SSL]
else:
secure = False
if not secure == request.is_secure():
f=open('/tmp/workfile', 'a')
f.write( "\nrequest.is_secure: "+str(request.is_secure()) )
f.write( "\nrequest.build_absolute_uri: "+request.build_absolute_uri() )
f.close()
if secure and settings.SSL_ENABLED:
return self._redirect(request, secure)
def _redirect(self, request, secure):
if settings.DEBUG and request.method == 'POST':
raise RuntimeError(
"""Django can't perform a SSL redirect while maintaining POST data.
Please structure your views so that redirects only occur during GETs.""")
protocol = secure and "https" or "http"
newurl = "%s://%s%s" % (protocol,get_host(request),request.get_full_path())
f=open('/tmp/workfile', 'a')
f.write( "\nnewurl: "+newurl )
f.close()
os.environ["HTTPS"] = "on"
os.environ['wsgi.url_scheme'] = 'https'
return HttpResponsePermanentRedirect(newurl)
#original — http://www.fairviewcomputing.com/blog/2008/10/23/django-wsgi-handler-ssl-proxies/
#some changes to get right environment
#project.wsgi
import os, sys
sys.path.insert(0, '/project/django')
sys.path.insert(1, '/project')
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'
os.environ['PYTHON_EGG_CACHE'] = '/project/pythoneggs'
import logging
from django.conf import settings
import django.core.handlers.wsgi
class WSGIRequest(django.core.handlers.wsgi.WSGIRequest):
def is_secure(self):
logger = logging.getLogger('project.wsgi.WSGIRequest.is_secure')
header = getattr(settings,
'FC_WSGI_PROTOCOL_HEADER',
'HTTP_X_FORWARDED_PROTO'
)
https_value = getattr(settings,
'FC_WSGI_PROTOCOL_HTTPS_VALUE',
'https'
).lower()
http_value = getattr(settings,
'FC_WSGI_PROTOCOL_HTTP_VALUE',
'http'
).lower()
value = self.META.get(header, '').lower()
if settings.DEBUG:
logger.debug("""HEADER: '%s' HTTPS value: '%s' HTTP value: '%s' request value: '%s'""" % (header, https_value, http_value, value))
if value == https_value or os.environ.get('HTTPS','off') in ('on','1'):
if settings.DEBUG:
logger.debug("""Request is secure.""")
return True
if settings.DEBUG:
logger.debug("""Request is insecure.""")
return False
class WSGIHandler(django.core.handlers.wsgi.WSGIHandler):
request_class = WSGIRequest
_application = WSGIHandler()
def application(environ, start_response):
environ['PATH_INFO'] = environ['SCRIPT_NAME'] + environ['PATH_INFO']
if environ.get('HTTPS','off') in ('on','1'):
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
if environ['wsgi.url_scheme'] == 'https':
environ['HTTPS'] = 'on'
return _application(environ, start_response)