From 4209b6ceac4e93f3fe414b2aa30ba064524e9f71 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Mar 2024 15:09:39 +0100 Subject: [PATCH] Correct WSGI adapter handling of root path. Fixes #442 --- asgiref/wsgi.py | 8 ++++++-- setup.cfg | 2 +- tests/test_wsgi.py | 24 +++++++++++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/asgiref/wsgi.py b/asgiref/wsgi.py index bf1be604..65af4279 100644 --- a/asgiref/wsgi.py +++ b/asgiref/wsgi.py @@ -54,10 +54,14 @@ def build_environ(self, scope, body): """ Builds a scope and request body into a WSGI environ object. """ + script_name = scope.get("root_path", "").encode("utf8").decode("latin1") + path_info = scope["path"].encode("utf8").decode("latin1") + if path_info.startswith(script_name): + path_info = path_info[len(script_name) :] environ = { "REQUEST_METHOD": scope["method"], - "SCRIPT_NAME": scope.get("root_path", "").encode("utf8").decode("latin1"), - "PATH_INFO": scope["path"].encode("utf8").decode("latin1"), + "SCRIPT_NAME": script_name, + "PATH_INFO": path_info, "QUERY_STRING": scope["query_string"].decode("ascii"), "SERVER_PROTOCOL": "HTTP/%s" % scope["http_version"], "wsgi.version": (1, 0), diff --git a/setup.cfg b/setup.cfg index e98a079e..ab3364d6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -47,7 +47,7 @@ asyncio_mode = strict [flake8] exclude = venv/*,tox/*,specs/* -ignore = E123,E128,E266,E402,W503,E731,W601 +ignore = E123,E128,E266,E402,W503,E731,W601,E203 max-line-length = 119 [isort] diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py index aabea4df..5f50ce66 100644 --- a/tests/test_wsgi.py +++ b/tests/test_wsgi.py @@ -3,7 +3,7 @@ import pytest from asgiref.testing import ApplicationCommunicator -from asgiref.wsgi import WsgiToAsgi +from asgiref.wsgi import WsgiToAsgi, WsgiToAsgiInstance @pytest.mark.asyncio @@ -11,6 +11,7 @@ async def test_basic_wsgi(): """ Makes sure the WSGI wrapper has basic functionality. """ + # Define WSGI app def wsgi_application(environ, start_response): assert environ["HTTP_TEST_HEADER"] == "test value 1,test value 2" @@ -55,11 +56,32 @@ def wsgi_application(environ, start_response): assert (await instance.receive_output(1)) == {"type": "http.response.body"} +def test_script_name(): + scope = { + "type": "http", + "http_version": "1.0", + "method": "GET", + "root_path": "/base", + "path": "/base/foo/", + "query_string": b"bar=baz", + "headers": [ + [b"test-header", b"test value 1"], + [b"test-header", b"test value 2"], + ], + } + adapter = WsgiToAsgiInstance(None) + adapter.scope = scope + environ = adapter.build_environ(scope, None) + assert environ["SCRIPT_NAME"] == "/base" + assert environ["PATH_INFO"] == "/foo/" + + @pytest.mark.asyncio async def test_wsgi_path_encoding(): """ Makes sure the WSGI wrapper has basic functionality. """ + # Define WSGI app def wsgi_application(environ, start_response): assert environ["SCRIPT_NAME"] == "/中国".encode().decode("latin-1")