views:

167

answers:

0

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)