From 2c5fae5c5582cdc00535ca16b0b2f5e3d27c6244 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Tue, 26 Nov 2013 23:41:11 +0100 Subject: Add comments in DebugToolbarMiddleware. Reorder process_response slightly to ensure instrumentation is deactivated for streaming responses. --- debug_toolbar/middleware.py | 50 +++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'debug_toolbar/middleware.py') diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index b58f588..b6099d3 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -39,27 +39,35 @@ class DebugToolbarMiddleware(object): debug_toolbars = {} def process_request(self, request): + # Decide whether the toolbar is active for this request. func_path = dt_settings.CONFIG['SHOW_TOOLBAR_CALLBACK'] # Replace this with import_by_path in Django >= 1.6. mod_path, func_name = func_path.rsplit('.', 1) show_toolbar = getattr(import_module(mod_path), func_name) if not show_toolbar(request): return - response = None + toolbar = DebugToolbar(request) + self.__class__.debug_toolbars[threading.current_thread().ident] = toolbar + + # Activate instrumentation ie. monkey-patch. for panel in toolbar.enabled_panels: panel.enable_instrumentation() + + # Run process_request methods of panels like Django middleware. + response = None for panel in toolbar.enabled_panels: response = panel.process_request(request) if response: break - self.__class__.debug_toolbars[threading.current_thread().ident] = toolbar return response def process_view(self, request, view_func, view_args, view_kwargs): toolbar = self.__class__.debug_toolbars.get(threading.current_thread().ident) if not toolbar: return + + # Run process_view methods of panels like Django middleware. response = None for panel in toolbar.enabled_panels: response = panel.process_view(request, view_func, view_args, view_kwargs) @@ -69,26 +77,42 @@ class DebugToolbarMiddleware(object): def process_response(self, request, response): toolbar = self.__class__.debug_toolbars.pop(threading.current_thread().ident, None) - if not toolbar or getattr(response, 'streaming', False): + if not toolbar: return response + + # Run process_response methods of panels like Django middleware. for panel in reversed(toolbar.enabled_panels): new_response = panel.process_response(request, response) if new_response: response = new_response + + # Deactivate instrumentation ie. monkey-unpatch. This must run + # regardless of the response. Keep 'return' clauses below. + # (NB: Django's model for middleware doesn't guarantee anything.) for panel in reversed(toolbar.enabled_panels): panel.disable_instrumentation() + + # Check for responses where the toolbar can't be inserted. + content_encoding = response.get('Content-Encoding', '') + content_type = response.get('Content-Type', '').split(';')[0] + if any((getattr(response, 'streaming', False), + 'gzip' in content_encoding, + content_type not in _HTML_TYPES)): + return response + + # Collapse the toolbar by default if SHOW_COLLAPSED is set. if toolbar.config['SHOW_COLLAPSED'] and 'djdt' not in request.COOKIES: response.set_cookie('djdt', 'hide', 864000) - if ('gzip' not in response.get('Content-Encoding', '') and - response.get('Content-Type', '').split(';')[0] in _HTML_TYPES): - content = force_text(response.content, encoding=settings.DEFAULT_CHARSET) - try: - insert_at = content.lower().rindex(dt_settings.CONFIG['INSERT_BEFORE'].lower()) - except ValueError: - pass - else: - toolbar_content = toolbar.render_toolbar() - response.content = content[:insert_at] + toolbar_content + content[insert_at:] + + # Insert the toolbar in the response. + content = force_text(response.content, encoding=settings.DEFAULT_CHARSET) + try: + insert_at = content.lower().rindex(dt_settings.CONFIG['INSERT_BEFORE'].lower()) + except ValueError: + pass + else: + toolbar_content = toolbar.render_toolbar() + response.content = content[:insert_at] + toolbar_content + content[insert_at:] if response.get('Content-Length', None): response['Content-Length'] = len(response.content) return response -- cgit v1.2.3