Code

Ticket #730: explicit_middleware_ordering_t730_r8166.diff

File explicit_middleware_ordering_t730_r8166.diff, 4.7 KB (added by andrewbadr, 6 years ago)
Line 
1Index: django/core/handlers/base.py
2===================================================================
3--- django/core/handlers/base.py        (revision 8166)
4+++ django/core/handlers/base.py        (working copy)
5@@ -1,4 +1,4 @@
6-import sys
7+import sys, copy
8 
9 from django import http
10 from django.core import signals
11@@ -17,6 +17,25 @@
12     def __init__(self):
13         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
14 
15+    def middleware_class_from_path(middleware_path):
16+        from django.core import exceptions
17+        try:
18+            dot = middleware_path.rindex('.')
19+        except ValueError:
20+            raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
21+        mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
22+        try:
23+            mod = __import__(mw_module, {}, {}, [''])
24+        except ImportError, e:
25+            raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
26+        try:
27+            mw_class = getattr(mod, mw_classname)
28+        except AttributeError:
29+            raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
30+        return mw_class
31+    middleware_class_from_path = staticmethod(middleware_class_from_path)
32+
33+
34     def load_middleware(self):
35         """
36         Populate middleware lists from settings.MIDDLEWARE_CLASSES.
37@@ -29,34 +48,46 @@
38         self._view_middleware = []
39         self._response_middleware = []
40         self._exception_middleware = []
41-        for middleware_path in settings.MIDDLEWARE_CLASSES:
42-            try:
43-                dot = middleware_path.rindex('.')
44-            except ValueError:
45-                raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
46-            mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
47-            try:
48-                mod = __import__(mw_module, {}, {}, [''])
49-            except ImportError, e:
50-                raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
51-            try:
52-                mw_class = getattr(mod, mw_classname)
53-            except AttributeError:
54-                raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
55+       
56+        # Get incoming and outgoing middleware orders and make sure they contain the same paths
57+        incoming_middleware_order = settings.MIDDLEWARE_CLASSES
58+        if hasattr(settings, 'OUTGOING_MIDDLEWARE_ORDER'):
59+            outgoing_middleware_order = settings.OUTGOING_MIDDLEWARE_ORDER
60+            if not len(incoming_middleware_order) == len(outgoing_middleware_order):
61+                raise exceptions.ImproperlyConfigured, 'OUTGOING_MIDDLEWARE_ORDER must contain the same middleware as MIDDLEWARE_CLASSES'
62+            for middleware_path in incoming_middleware_order:
63+                if not middleware_path in outgoing_middleware_order:
64+                    raise exceptions.ImproperlyConfigured, 'OUTGOING_MIDDLEWARE_ORDER does not contain %s MIDDLEWARE_CLASSES' % middleware_path
65+        else:
66+            outgoing_middleware_order = copy.copy(incoming_middleware_order)
67+            outgoing_middleware_order.reverse()
68+       
69+        for middleware_path in incoming_middleware_order:
70+            mw_class = self.middleware_class_from_path(middleware_path)
71 
72             try:
73                 mw_instance = mw_class()
74             except exceptions.MiddlewareNotUsed:
75                 continue
76-
77+       
78             if hasattr(mw_instance, 'process_request'):
79                 self._request_middleware.append(mw_instance.process_request)
80             if hasattr(mw_instance, 'process_view'):
81                 self._view_middleware.append(mw_instance.process_view)
82+               
83+        for middleware_path in outgoing_middleware_order:
84+
85+            mw_class = self.middleware_class_from_path(middleware_path)
86+
87+            try:
88+                mw_instance = mw_class()
89+            except exceptions.MiddlewareNotUsed:
90+                continue
91+         
92             if hasattr(mw_instance, 'process_response'):
93-                self._response_middleware.insert(0, mw_instance.process_response)
94+                self._response_middleware.append(mw_instance.process_response)
95             if hasattr(mw_instance, 'process_exception'):
96-                self._exception_middleware.insert(0, mw_instance.process_exception)
97+                self._exception_middleware.append(mw_instance.process_exception)
98 
99     def get_response(self, request):
100         "Returns an HttpResponse object for the given HttpRequest"