Skip to content

Commit 0924116

Browse files
authored
Enhance RedirectsPanel with customizable redirect response hook (#2104)
* Add interception_response hook * Fix comments for SimpleTemplateResponse * Docs for Custom RedirectPanel * Moved the changelog entry to the correct place.
1 parent 0d7b859 commit 0924116

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

Diff for: debug_toolbar/panels/redirects.py

+21-14
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,8 @@ def _process_response(self, response):
2222
Common response processing logic.
2323
"""
2424
if 300 <= response.status_code < 400:
25-
redirect_to = response.get("Location")
26-
if redirect_to:
27-
status_line = f"{response.status_code} {response.reason_phrase}"
28-
cookies = response.cookies
29-
context = {
30-
"redirect_to": redirect_to,
31-
"status_line": status_line,
32-
"toolbar": self.toolbar,
33-
}
34-
# Using SimpleTemplateResponse avoids running global context processors.
35-
response = SimpleTemplateResponse(
36-
"debug_toolbar/redirect.html", context
37-
)
38-
response.cookies = cookies
25+
if redirect_to := response.get("Location"):
26+
response = self.get_interception_response(response, redirect_to)
3927
response.render()
4028
return response
4129

@@ -53,3 +41,22 @@ def process_request(self, request):
5341
if iscoroutine(response):
5442
return self.aprocess_request(request, response)
5543
return self._process_response(response)
44+
45+
def get_interception_response(self, response, redirect_to):
46+
"""
47+
Hook method to allow subclasses to customize the interception response.
48+
"""
49+
status_line = f"{response.status_code} {response.reason_phrase}"
50+
cookies = response.cookies
51+
original_response = response
52+
context = {
53+
"redirect_to": redirect_to,
54+
"status_line": status_line,
55+
"toolbar": self.toolbar,
56+
"original_response": original_response,
57+
}
58+
# Using SimpleTemplateResponse avoids running global context processors.
59+
response = SimpleTemplateResponse("debug_toolbar/redirect.html", context)
60+
response.cookies = cookies
61+
response.original_response = original_response
62+
return response

Diff for: docs/changes.rst

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Change log
44
Pending
55
-------
66

7+
* Added hook to RedirectsPanel for subclass customization.
8+
79
5.1.0 (2025-03-20)
810
------------------
911
* Added Django 5.2 to the tox matrix.

Diff for: docs/panels.rst

+5
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ Since this behavior is annoying when you aren't debugging a redirect, this
122122
panel is included but inactive by default. You can activate it by default with
123123
the ``DISABLE_PANELS`` configuration option.
124124

125+
To further customize the behavior, you can subclass the ``RedirectsPanel``
126+
and override the ``get_interception_response`` method to manipulate the
127+
response directly. To use a custom ``RedirectsPanel``, you need to replace
128+
the original one in ``DEBUG_TOOLBAR_PANELS`` in your ``settings.py``.
129+
125130
.. _profiling-panel:
126131

127132
Profiling

Diff for: tests/panels/test_redirects.py

+13
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,16 @@ async def get_response(request):
8585
response = await self.panel.process_request(self.request)
8686
self.assertIsInstance(response, HttpResponse)
8787
self.assertTrue(response is await_response)
88+
89+
def test_original_response_preserved(self):
90+
redirect = HttpResponse(status=302)
91+
redirect["Location"] = "http://somewhere/else/"
92+
self._get_response = lambda request: redirect
93+
response = self.panel.process_request(self.request)
94+
self.assertFalse(response is redirect)
95+
self.assertTrue(hasattr(response, "original_response"))
96+
self.assertTrue(response.original_response is redirect)
97+
self.assertIsNone(response.get("Location"))
98+
self.assertEqual(
99+
response.original_response.get("Location"), "http://somewhere/else/"
100+
)

0 commit comments

Comments
 (0)