Skip to content

Commit 23bb473

Browse files
dmartinmatthiask
authored andcommitted
Make toolbar compatible with FORCE_SCRIPT_NAME
Previously, if a project used the `FORCE_SCRIPT_NAME` setting (common when hosting a Django application on a subdirectory path via a reverse proxy), the `django.urls.resolve()` call would always raise `Resolver404` in the middleware. As a result, `is_toolbar_request()` always returned False. This caused internal toolbar URLs to be inspected, and also indirectly led to a request loop when refreshing the history panel. In most cases (if `FORCE_SCRIPT_NAME` is unset), `get_script_prefix()` will return "/" and the `replace()` will be a no-op.
1 parent 5d4e97f commit 23bb473

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

debug_toolbar/toolbar.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from django.dispatch import Signal
1414
from django.template import TemplateSyntaxError
1515
from django.template.loader import render_to_string
16-
from django.urls import include, path, re_path, resolve
16+
from django.urls import get_script_prefix, include, path, re_path, resolve
1717
from django.urls.exceptions import Resolver404
1818
from django.utils.module_loading import import_string
1919
from django.utils.translation import get_language, override as lang_override
@@ -165,7 +165,8 @@ def is_toolbar_request(cls, request):
165165
# not have resolver_match set.
166166
try:
167167
resolver_match = request.resolver_match or resolve(
168-
request.path, getattr(request, "urlconf", None)
168+
request.path.replace(get_script_prefix(), "/", 1),
169+
getattr(request, "urlconf", None),
169170
)
170171
except Resolver404:
171172
return False

docs/changes.rst

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

7+
* Fixed internal toolbar requests being instrumented if the Django setting
8+
``FORCE_SCRIPT_NAME`` was set.
9+
710
4.4.6 (2024-07-10)
811
------------------
912

tests/test_integration.py

+17
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,23 @@ def test_is_toolbar_request_override_request_urlconf(self):
244244
self.request.path = "/__debug__/render_panel/"
245245
self.assertTrue(self.toolbar.is_toolbar_request(self.request))
246246

247+
@patch("debug_toolbar.toolbar.get_script_prefix", return_value="/path/")
248+
def test_is_toolbar_request_with_script_prefix(self, mocked_get_script_prefix):
249+
"""
250+
Test cases when Django is running under a path prefix, such as via the
251+
FORCE_SCRIPT_NAME setting.
252+
"""
253+
self.request.path = "/path/__debug__/render_panel/"
254+
self.assertTrue(self.toolbar.is_toolbar_request(self.request))
255+
256+
self.request.path = "/path/invalid/__debug__/render_panel/"
257+
self.assertFalse(self.toolbar.is_toolbar_request(self.request))
258+
259+
self.request.path = "/path/render_panel/"
260+
self.assertFalse(self.toolbar.is_toolbar_request(self.request))
261+
262+
self.assertEqual(mocked_get_script_prefix.call_count, 3)
263+
247264
def test_data_gone(self):
248265
response = self.client.get(
249266
"/__debug__/render_panel/?store_id=GONE&panel_id=RequestPanel"

0 commit comments

Comments
 (0)