From 041b0a359a0a80e147b47c6ae5f11bca9dd3b28a Mon Sep 17 00:00:00 2001 From: sarahboyce Date: Mon, 10 Apr 2023 17:10:43 +0200 Subject: [PATCH] Fixed #34394 -- Added FORCE_SCRIPT_NAME handling to ASGIRequest. Co-authored-by: Mariusz Felisiak --- django/core/handlers/asgi.py | 21 +++++++++++---------- tests/handlers/tests.py | 7 +++++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/django/core/handlers/asgi.py b/django/core/handlers/asgi.py index 846bece39b..0edc98854f 100644 --- a/django/core/handlers/asgi.py +++ b/django/core/handlers/asgi.py @@ -26,6 +26,15 @@ from django.utils.functional import cached_property logger = logging.getLogger("django.request") +def get_script_prefix(scope): + """ + Return the script prefix to use from either the scope or a setting. + """ + if settings.FORCE_SCRIPT_NAME: + return settings.FORCE_SCRIPT_NAME + return scope.get("root_path", "") or "" + + class ASGIRequest(HttpRequest): """ Custom request subclass that decodes from an ASGI-standard request dict @@ -41,7 +50,7 @@ class ASGIRequest(HttpRequest): self._post_parse_error = False self._read_started = False self.resolver_match = None - self.script_name = self.scope.get("root_path", "") + self.script_name = get_script_prefix(scope) if self.script_name: # TODO: Better is-prefix checking, slash handling? self.path_info = scope["path"].removeprefix(self.script_name) @@ -170,7 +179,7 @@ class ASGIHandler(base.BaseHandler): except RequestAborted: return # Request is complete and can be served. - set_script_prefix(self.get_script_prefix(scope)) + set_script_prefix(get_script_prefix(scope)) await signals.request_started.asend(sender=self.__class__, scope=scope) # Get the request and check for basic issues. request, error_response = self.create_request(scope, body_file) @@ -344,11 +353,3 @@ class ASGIHandler(base.BaseHandler): (position + cls.chunk_size) >= len(data), ) position += cls.chunk_size - - def get_script_prefix(self, scope): - """ - Return the script prefix to use from either the scope or a setting. - """ - if settings.FORCE_SCRIPT_NAME: - return settings.FORCE_SCRIPT_NAME - return scope.get("root_path", "") or "" diff --git a/tests/handlers/tests.py b/tests/handlers/tests.py index 0348b8e5d6..ab3837d25e 100644 --- a/tests/handlers/tests.py +++ b/tests/handlers/tests.py @@ -3,6 +3,7 @@ from django.core.handlers.wsgi import WSGIHandler, WSGIRequest, get_script_name from django.core.signals import request_finished, request_started from django.db import close_old_connections, connection from django.test import ( + AsyncRequestFactory, RequestFactory, SimpleTestCase, TransactionTestCase, @@ -328,6 +329,12 @@ class AsyncHandlerRequestTests(SimpleTestCase): with self.assertRaisesMessage(ValueError, msg): await self.async_client.get("/unawaited/") + @override_settings(FORCE_SCRIPT_NAME="/FORCED_PREFIX/") + def test_force_script_name(self): + async_request_factory = AsyncRequestFactory() + request = async_request_factory.request(**{"path": "/somepath/"}) + self.assertEqual(request.path, "/FORCED_PREFIX/somepath/") + async def test_sync_streaming(self): response = await self.async_client.get("/streaming/") self.assertEqual(response.status_code, 200)