All articles, tagged with “https”

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:

#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)