From c97efb6799168c8903fc1181ecada7fe9932dd1f Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 22 Jul 2005 18:34:38 +0000 Subject: [PATCH] Fixed #63 -- Refactored django.core.handlers into subclasses to remove duplicate code git-svn-id: http://code.djangoproject.com/svn/django/trunk@298 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/handlers/base.py | 117 +++++++++++++++++++++++++++++ django/core/handlers/modpython.py | 118 +----------------------------- django/core/handlers/wsgi.py | 118 +----------------------------- 3 files changed, 121 insertions(+), 232 deletions(-) create mode 100644 django/core/handlers/base.py diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py new file mode 100644 index 0000000000..5a5bf69d2f --- /dev/null +++ b/django/core/handlers/base.py @@ -0,0 +1,117 @@ +from django.utils import httpwrappers + +class BaseHandler: + def __init__(self): + self._request_middleware = self._view_middleware = self._response_middleware = None + + def load_middleware(self): + """ + Populate middleware lists from settings.MIDDLEWARE_CLASSES. + + Must be called after the environment is fixed (see __call__). + """ + from django.conf import settings + from django.core import exceptions + self._request_middleware = [] + self._view_middleware = [] + self._response_middleware = [] + for middleware_path in settings.MIDDLEWARE_CLASSES: + dot = middleware_path.rindex('.') + mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:] + try: + mod = __import__(mw_module, '', '', ['']) + except ImportError, e: + raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e) + try: + mw_class = getattr(mod, mw_classname) + except AttributeError: + raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname) + + try: + mw_instance = mw_class() + except exceptions.MiddlewareNotUsed: + continue + + if hasattr(mw_instance, 'process_request'): + self._request_middleware.append(mw_instance.process_request) + if hasattr(mw_instance, 'process_view'): + self._view_middleware.append(mw_instance.process_view) + if hasattr(mw_instance, 'process_response'): + self._response_middleware.insert(0, mw_instance.process_response) + + def get_response(self, path, request): + "Returns an HttpResponse object for the given HttpRequest" + from django.core import db, exceptions, urlresolvers + from django.core.mail import mail_admins + from django.conf.settings import DEBUG, INTERNAL_IPS, ROOT_URLCONF + + # Apply request middleware + for middleware_method in self._request_middleware: + response = middleware_method(request) + if response: + return response + + conf_module = __import__(ROOT_URLCONF, '', '', ['']) + resolver = urlresolvers.RegexURLResolver(conf_module.urlpatterns) + try: + callback, param_dict = resolver.resolve(path) + # Apply view middleware + for middleware_method in self._view_middleware: + response = middleware_method(request, callback, param_dict) + if response: + return response + return callback(request, **param_dict) + except exceptions.Http404: + if DEBUG: + return self.get_technical_error_response(is404=True) + else: + resolver = urlresolvers.Error404Resolver(conf_module.handler404) + callback, param_dict = resolver.resolve() + return callback(request, **param_dict) + except db.DatabaseError: + db.db.rollback() + if DEBUG: + return self.get_technical_error_response() + else: + subject = 'Database error (%s IP)' % (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL') + message = "%s\n\n%s" % (self._get_traceback(), request) + mail_admins(subject, message, fail_silently=True) + return self.get_friendly_error_response(request, conf_module) + except exceptions.PermissionDenied: + return httpwrappers.HttpResponseForbidden('

Permission denied

') + except: # Handle everything else, including SuspiciousOperation, etc. + if DEBUG: + return self.get_technical_error_response() + else: + subject = 'Coding error (%s IP)' % (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL') + try: + request_repr = repr(request) + except: + request_repr = "Request repr() unavailable" + message = "%s\n\n%s" % (self._get_traceback(), request_repr) + mail_admins(subject, message, fail_silently=True) + return self.get_friendly_error_response(request, conf_module) + + def get_friendly_error_response(self, request, conf_module): + """ + Returns an HttpResponse that displays a PUBLIC error message for a + fundamental database or coding error. + """ + from django.core import urlresolvers + resolver = urlresolvers.Error404Resolver(conf_module.handler500) + callback, param_dict = resolver.resolve() + return callback(request, **param_dict) + + def get_technical_error_response(self, is404=False): + """ + Returns an HttpResponse that displays a TECHNICAL error message for a + fundamental database or coding error. + """ + error_string = "There's been an error:\n\n%s" % self._get_traceback() + responseClass = is404 and httpwrappers.HttpResponseNotFound or httpwrappers.HttpResponseServerError + return responseClass(error_string, mimetype='text/plain') + + def _get_traceback(self): + "Helper function to return the traceback as a string" + import sys, traceback + return '\n'.join(traceback.format_exception(*sys.exc_info())) diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py index 0ab186eb01..efc82f0cfd 100644 --- a/django/core/handlers/modpython.py +++ b/django/core/handlers/modpython.py @@ -1,3 +1,4 @@ +from django.core.handlers.base import BaseHandler from django.utils import datastructures, httpwrappers from pprint import pformat import os @@ -124,10 +125,7 @@ class ModPythonRequest(httpwrappers.HttpRequest): session = property(_get_session, _set_session) user = property(_get_user, _set_user) -class ModPythonHandler: - def __init__(self): - self._request_middleware = self._view_middleware = self._response_middleware = None - +class ModPythonHandler(BaseHandler): def __call__(self, req): # mod_python fakes the environ, and thus doesn't process SetEnv. This fixes that os.environ.update(req.subprocess_env) @@ -155,118 +153,6 @@ class ModPythonHandler: populate_apache_request(response, req) return 0 # mod_python.apache.OK - def load_middleware(self): - """ - Populate middleware lists from settings.MIDDLEWARE_CLASSES. - - Must be called after the environment is fixed (see __call__). - """ - from django.conf import settings - from django.core import exceptions - self._request_middleware = [] - self._view_middleware = [] - self._response_middleware = [] - for middleware_path in settings.MIDDLEWARE_CLASSES: - dot = middleware_path.rindex('.') - mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:] - try: - mod = __import__(mw_module, '', '', ['']) - except ImportError, e: - raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e) - try: - mw_class = getattr(mod, mw_classname) - except AttributeError: - raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname) - - try: - mw_instance = mw_class() - except exceptions.MiddlewareNotUsed: - continue - - if hasattr(mw_instance, 'process_request'): - self._request_middleware.append(mw_instance.process_request) - if hasattr(mw_instance, 'process_view'): - self._view_middleware.append(mw_instance.process_view) - if hasattr(mw_instance, 'process_response'): - self._response_middleware.insert(0, mw_instance.process_response) - - def get_response(self, path, request): - "Returns an HttpResponse object for the given HttpRequest" - from django.core import db, exceptions, urlresolvers - from django.core.mail import mail_admins - from django.conf.settings import DEBUG, INTERNAL_IPS, ROOT_URLCONF - - # Apply request middleware - for middleware_method in self._request_middleware: - response = middleware_method(request) - if response: - return response - - conf_module = __import__(ROOT_URLCONF, '', '', ['']) - resolver = urlresolvers.RegexURLResolver(conf_module.urlpatterns) - try: - callback, param_dict = resolver.resolve(path) - # Apply view middleware - for middleware_method in self._view_middleware: - response = middleware_method(request, callback, param_dict) - if response: - return response - return callback(request, **param_dict) - except exceptions.Http404: - if DEBUG: - return self.get_technical_error_response(is404=True) - else: - resolver = urlresolvers.Error404Resolver(conf_module.handler404) - callback, param_dict = resolver.resolve() - return callback(request, **param_dict) - except db.DatabaseError: - db.db.rollback() - if DEBUG: - return self.get_technical_error_response() - else: - subject = 'Database error (%s IP)' % (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL') - message = "%s\n\n%s" % (self._get_traceback(), request) - mail_admins(subject, message, fail_silently=True) - return self.get_friendly_error_response(request, conf_module) - except exceptions.PermissionDenied: - return httpwrappers.HttpResponseForbidden('

Permission denied

') - except: # Handle everything else, including SuspiciousOperation, etc. - if DEBUG: - return self.get_technical_error_response() - else: - subject = 'Coding error (%s IP)' % (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL') - try: - request_repr = repr(request) - except: - request_repr = "Request repr() unavailable" - message = "%s\n\n%s" % (self._get_traceback(), request_repr) - mail_admins(subject, message, fail_silently=True) - return self.get_friendly_error_response(request, conf_module) - - def get_friendly_error_response(self, request, conf_module): - """ - Returns an HttpResponse that displays a PUBLIC error message for a - fundamental database or coding error. - """ - from django.core import urlresolvers - resolver = urlresolvers.Error404Resolver(conf_module.handler500) - callback, param_dict = resolver.resolve() - return callback(request, **param_dict) - - def get_technical_error_response(self, is404=False): - """ - Returns an HttpResponse that displays a TECHNICAL error message for a - fundamental database or coding error. - """ - error_string = "There's been an error:\n\n%s" % self._get_traceback() - responseClass = is404 and httpwrappers.HttpResponseNotFound or httpwrappers.HttpResponseServerError - return responseClass(error_string, mimetype='text/plain') - - def _get_traceback(self): - "Helper function to return the traceback as a string" - import sys, traceback - return '\n'.join(traceback.format_exception(*sys.exc_info())) - def populate_apache_request(http_response, mod_python_req): "Populates the mod_python request object with an HttpResponse" mod_python_req.content_type = http_response['Content-Type'] or httpwrappers.DEFAULT_MIME_TYPE diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 75415ab5ad..9f0c035c53 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -1,3 +1,4 @@ +from django.core.handlers.base import BaseHandler from django.utils import datastructures, httpwrappers from pprint import pformat @@ -104,10 +105,7 @@ class WSGIRequest(httpwrappers.HttpRequest): session = property(_get_session, _set_session) user = property(_get_user, _set_user) -class WSGIHandler: - def __init__(self): - self._request_middleware = self._view_middleware = self._response_middleware = None - +class WSGIHandler(BaseHandler): def __call__(self, environ, start_response): from django.conf import settings from django.core import db @@ -139,118 +137,6 @@ class WSGIHandler: start_response(status, response_headers.items()) return output - def load_middleware(self): - """ - Populate middleware lists from settings.MIDDLEWARE_CLASSES. - - Must be called after the environment is fixed (see __call__). - """ - from django.conf import settings - from django.core import exceptions - self._request_middleware = [] - self._view_middleware = [] - self._response_middleware = [] - for middleware_path in settings.MIDDLEWARE_CLASSES: - dot = middleware_path.rindex('.') - mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:] - try: - mod = __import__(mw_module, '', '', ['']) - except ImportError, e: - raise exceptions.ImproperlyConfigured, \ - 'Error importing middleware %s: "%s"' % (mw_module, e) - try: - mw_class = getattr(mod, mw_classname) - except AttributeError: - raise exceptions.ImproperlyConfigured, \ - 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname) - - try: - mw_instance = mw_class() - except exceptions.MiddlewareNotUsed: - continue - - if hasattr(mw_instance, 'process_request'): - self._request_middleware.append(mw_instance.process_request) - if hasattr(mw_instance, 'process_view'): - self._view_middleware.append(mw_instance.process_view) - if hasattr(mw_instance, 'process_response'): - self._response_middleware.insert(0, mw_instance.process_response) - - def get_response(self, path, request): - "Returns an HttpResponse object for the given HttpRequest" - from django.core import db, exceptions, urlresolvers - from django.core.mail import mail_admins - from django.conf.settings import DEBUG, INTERNAL_IPS, ROOT_URLCONF - - # Apply request middleware - for middleware_method in self._request_middleware: - response = middleware_method(request) - if response: - return response - - conf_module = __import__(ROOT_URLCONF, '', '', ['']) - resolver = urlresolvers.RegexURLResolver(conf_module.urlpatterns) - try: - callback, param_dict = resolver.resolve(path) - # Apply view middleware - for middleware_method in self._view_middleware: - response = middleware_method(request, callback, param_dict) - if response: - return response - return callback(request, **param_dict) - except exceptions.Http404: - if DEBUG: - return self.get_technical_error_response(is404=True) - else: - resolver = urlresolvers.Error404Resolver(conf_module.handler404) - callback, param_dict = resolver.resolve() - return callback(request, **param_dict) - except db.DatabaseError: - db.db.rollback() - if DEBUG: - return self.get_technical_error_response() - else: - subject = 'Database error (%s IP)' % \ - (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL') - message = "%s\n\n%s" % (self._get_traceback(), request) - mail_admins(subject, message, fail_silently=True) - return self.get_friendly_error_response(request, conf_module) - except exceptions.PermissionDenied: - return httpwrappers.HttpResponseForbidden('

Permission denied

') - except: # Handle everything else, including SuspiciousOperation, etc. - if DEBUG: - return self.get_technical_error_response() - else: - subject = 'Coding error (%s IP)' % \ - (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL') - message = "%s\n\n%s" % (self._get_traceback(), request) - mail_admins(subject, message, fail_silently=True) - return self.get_friendly_error_response(request, conf_module) - - def get_friendly_error_response(self, request, conf_module): - """ - Returns an HttpResponse that displays a PUBLIC error message for a - fundamental database or coding error. - """ - from django.core import urlresolvers - resolver = urlresolvers.Error404Resolver(conf_module.handler500) - callback, param_dict = resolver.resolve() - return callback(request, **param_dict) - - def get_technical_error_response(self, is404=False): - """ - Returns an HttpResponse that displays a TECHNICAL error message for a - fundamental database or coding error. - """ - error_string = "There's been an error:\n\n%s" % self._get_traceback() - responseClass = is404 and httpwrappers.HttpResponseNotFound or httpwrappers.HttpResponseServerError - return responseClass(error_string, mimetype='text/plain') - - def _get_traceback(self): - "Helper function to return the traceback as a string" - import sys, traceback - return '\n'.join(traceback.format_exception(*sys.exc_info())) - class AdminMediaHandler: """ WSGI middleware that intercepts calls to the admin media directory, as