HTTPS with django and WSGI
Fighting with deployed django app over WSGI with SSL enabled, I’ve found this snippet for middleware and this receipt for wsgi script.
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:
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)