I have set up nginx to handle SSL requests and send them to Apache/mod_python as described in http://code.google.com/p/mango-py/wiki/SSLRedirect. I added the django Middleware. I do proxy_set_header in nginx as described in http://yuji.wordpress.com/2008/08/15/django-nginx-making-ssl-work-on-django-behind-a-reverse-proxy/. This is intended to solve the problem of redirect loops, but I still get an endless redirect loop.
The SSL section of my nginx conf file is:
server {
listen 443;
server_name 12.345.67.89;
ssl on;
ssl_certificate server.crt;
ssl_certificate_key server.key;
keepalive_timeout 60;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Ssl on;
}
}
SSLMiddleware.py:
from django.conf import settings
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect, get_host
SSL = 'SSL'
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 == self._is_secure(request):
return self._redirect(request, secure)
def _is_secure(self, request):
if request.is_secure():
return True
#Handle the Webfaction case until this gets resolved in the request.is_secure()
if 'HTTP_X_FORWARDED_SSL' in request.META:
return request.META['HTTP_X_FORWARDED_SSL'] == 'on'
return False
def _redirect(self, request, secure):
protocol = secure and "https" or "http"
host = get_host(request)
# if we are being proxied use the default behavoir. Thus proxied servers will only work if outside the proxy they look like they are on standard ports.
if 'HTTP_X_FORWARDED_HOST' not in request.META:
if hasattr(settings,'HTTP_REDIRECT_TO_HTTPS'):
host = settings.HTTP_REDIRECT_TO_HTTPS
if hasattr(settings,'HTTP_REDIRECT_TO_HTTPS_PORT'):
host = host.split(":")[0] + ":" + str(settings.HTTP_REDIRECT_TO_HTTPS_PORT)
newurl = "%s://%s%s" % (protocol,host,request.get_full_path())
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."""
return HttpResponsePermanentRedirect(newurl)