Skip to content

Commit 405f9f2

Browse files
authored
Async compatible redirect panel (#1976)
* make redirect panel async capable by using aprocess_request patterm * added async compability test for redirect panel * remove redundant call for super process_request
1 parent 89568d5 commit 405f9f2

File tree

4 files changed

+39
-4
lines changed

4 files changed

+39
-4
lines changed

debug_toolbar/panels/redirects.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from inspect import iscoroutine
2+
13
from django.template.response import SimpleTemplateResponse
24
from django.utils.translation import gettext_lazy as _
35

@@ -9,13 +11,15 @@ class RedirectsPanel(Panel):
911
Panel that intercepts redirects and displays a page with debug info.
1012
"""
1113

12-
is_async = False
14+
is_async = True
1315
has_content = False
1416

1517
nav_title = _("Intercept redirects")
1618

17-
def process_request(self, request):
18-
response = super().process_request(request)
19+
def _process_response(self, response):
20+
"""
21+
Common response processing logic.
22+
"""
1923
if 300 <= response.status_code < 400:
2024
redirect_to = response.get("Location")
2125
if redirect_to:
@@ -33,3 +37,18 @@ def process_request(self, request):
3337
response.cookies = cookies
3438
response.render()
3539
return response
40+
41+
async def aprocess_request(self, request, response_coroutine):
42+
"""
43+
Async version of process_request. used for accessing the response
44+
by awaiting it when running in ASGI.
45+
"""
46+
47+
response = await response_coroutine
48+
return self._process_response(response)
49+
50+
def process_request(self, request):
51+
response = super().process_request(request)
52+
if iscoroutine(response):
53+
return self.aprocess_request(request, response)
54+
return self._process_response(response)

docs/architecture.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Problematic Parts
8282
- Support for async and multi-threading: ``debug_toolbar.middleware.DebugToolbarMiddleware``
8383
is now async compatible and can process async requests. However certain
8484
panels such as ``SQLPanel``, ``TimerPanel``, ``StaticFilesPanel``,
85-
``RequestPanel``, ``RedirectsPanel`` and ``ProfilingPanel`` aren't fully
85+
``RequestPanel`` and ``ProfilingPanel`` aren't fully
8686
compatible and currently being worked on. For now, these panels
8787
are disabled by default when running in async environment.
8888
follow the progress of this issue in `Async compatible toolbar project <https://github.com/orgs/jazzband/projects/9>`_.

docs/changes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Pending
88
* Fixed internal toolbar requests being instrumented if the Django setting
99
``FORCE_SCRIPT_NAME`` was set.
1010
* Increase opacity of show Debug Toolbar handle to improve accessibility.
11+
* Changed the ``RedirectsPanel`` to be async compatible.
1112

1213
4.4.6 (2024-07-10)
1314
------------------

tests/panels/test_redirects.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.conf import settings
44
from django.http import HttpResponse
5+
from django.test import AsyncRequestFactory
56

67
from ..base import BaseTestCase
78

@@ -70,3 +71,17 @@ def test_insert_content(self):
7071
self.assertIsNotNone(response)
7172
response = self.panel.generate_stats(self.request, redirect)
7273
self.assertIsNone(response)
74+
75+
async def test_async_compatibility(self):
76+
redirect = HttpResponse(status=302)
77+
78+
async def get_response(request):
79+
return redirect
80+
81+
await_response = await get_response(self.request)
82+
self._get_response = get_response
83+
84+
self.request = AsyncRequestFactory().get("/")
85+
response = await self.panel.process_request(self.request)
86+
self.assertIsInstance(response, HttpResponse)
87+
self.assertTrue(response is await_response)

0 commit comments

Comments
 (0)