diff --git a/src/asgi/utils.rs b/src/asgi/utils.rs index 35618920..b9077611 100644 --- a/src/asgi/utils.rs +++ b/src/asgi/utils.rs @@ -17,7 +17,7 @@ macro_rules! scope_native_parts { .uri .path_and_query() .map_or_else(|| ("", ""), |pq| (pq.path(), pq.query().unwrap_or(""))); - let $path = percent_encoding::percent_decode_str(path_raw).decode_utf8().unwrap(); + let $path = percent_encoding::percent_decode_str(path_raw).decode_utf8_lossy(); let $version = match $req.version { hyper::Version::HTTP_10 => "1", hyper::Version::HTTP_11 => "1.1", diff --git a/src/rsgi/types.rs b/src/rsgi/types.rs index c36a9599..3e012569 100644 --- a/src/rsgi/types.rs +++ b/src/rsgi/types.rs @@ -184,8 +184,8 @@ macro_rules! rsgi_scope_cls { } #[getter(path)] - fn get_path(&self) -> Result> { - Ok(percent_decode_str(self.uri.path()).decode_utf8()?) + fn get_path(&self) -> Cow { + percent_decode_str(self.uri.path()).decode_utf8_lossy() } #[getter(query_string)] diff --git a/tests/apps/asgi.py b/tests/apps/asgi.py index 723bfbf3..bd2f67e1 100644 --- a/tests/apps/asgi.py +++ b/tests/apps/asgi.py @@ -174,5 +174,5 @@ def app(scope, receive, send): '/err_app': err_app, '/err_proto': err_proto, '/timeout_n': timeout_n, - '/timeout_w': timeout_w, - }[scope['path']](scope, receive, send) + '/timeout_w': timeout_w + }.get(scope['path'], info)(scope, receive, send) diff --git a/tests/test_asgi.py b/tests/test_asgi.py index 602d6671..31855749 100644 --- a/tests/test_asgi.py +++ b/tests/test_asgi.py @@ -27,6 +27,18 @@ async def test_scope(asgi_server, threading_mode): assert data['state']['global'] == 'test' +@pytest.mark.asyncio +@pytest.mark.skipif(bool(os.getenv('PGO_RUN')), reason='PGO build') +@pytest.mark.parametrize('threading_mode', ['runtime', 'workers']) +async def test_scope_path_utf8_lossy(asgi_server, threading_mode): + async with asgi_server(threading_mode) as port: + res = httpx.get(f'http://localhost:{port}/%c0') + + assert res.status_code == 200 + data = res.json() + assert data['path'] == '/\ufffd' + + @pytest.mark.asyncio @pytest.mark.parametrize('threading_mode', ['runtime', 'workers']) async def test_body(asgi_server, threading_mode):