from django.conf import settings from django.core.exceptions import SuspiciousOperation import types import re USE_X_FORWARDED_FOR = getattr(settings, 'USE_X_FORWARDED_FOR', False) ip_validation_re = re.compile(r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$") class RequestAddrMiddleware(object): """ Adds a get_addr() method to the request object which returns an IP address based on X-Forwarded-For header if present and USE_X_FORWARDED_FOR setting is True (default is False) or REMOTE_ADDR meta attribute otherwise. """ def process_request(self, request): """Called on each request, before Django decides which view to execute.""" def get_addr(inst): """Returns the client IP address using the environment or request headers.""" if USE_X_FORWARDED_FOR and 'HTTP_X_FORWARDED_FOR' in inst.META: addr = inst.META['HTTP_X_FORWARDED_FOR'].split(",",1)[0].strip() elif 'REMOTE_ADDR' in inst.META: addr = inst.META['REMOTE_ADDR'] else: addr = "127.0.0.1" #Couldn't determine actual client IP! if not ip_validation_re.match(addr): raise SuspiciousOperation("Invalid client IP: %s" % addr) return addr request.get_addr = types.MethodType(get_addr, request, request.__class__)