]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Fix ASGITransport path escaping (#1307)
authorTom Christie <tom@tomchristie.com>
Wed, 23 Sep 2020 08:37:19 +0000 (09:37 +0100)
committerGitHub <noreply@github.com>
Wed, 23 Sep 2020 08:37:19 +0000 (09:37 +0100)
httpx/_transports/asgi.py
tests/test_asgi.py

index 94976f3aad0dd42612cc99cd022a5f68f5f0e1b5..b47f68b547aa57478767749ccc5bfa94766d2710 100644 (file)
@@ -1,4 +1,5 @@
 from typing import TYPE_CHECKING, Callable, List, Optional, Tuple, Union
+from urllib.parse import unquote
 
 import httpcore
 import sniffio
@@ -88,7 +89,7 @@ class ASGITransport(httpcore.AsyncHTTPTransport):
             "method": method.decode(),
             "headers": headers,
             "scheme": scheme.decode("ascii"),
-            "path": path.decode("ascii"),
+            "path": unquote(path.decode("ascii")),
             "query_string": query,
             "server": (host.decode("ascii"), port),
             "client": self.client,
index 70da3c54ad13a696976c39f6e1a23029e416d841..4aac735a532f71dfcf8184b6173f5a6e27288968 100644 (file)
@@ -1,3 +1,5 @@
+import json
+
 import pytest
 
 import httpx
@@ -12,6 +14,15 @@ async def hello_world(scope, receive, send):
     await send({"type": "http.response.body", "body": output})
 
 
+async def echo_path(scope, receive, send):
+    status = 200
+    output = json.dumps({"path": scope["path"]}).encode("utf-8")
+    headers = [(b"content-type", "text/plain"), (b"content-length", str(len(output)))]
+
+    await send({"type": "http.response.start", "status": status, "headers": headers})
+    await send({"type": "http.response.body", "body": output})
+
+
 async def echo_body(scope, receive, send):
     status = 200
     headers = [(b"content-type", "text/plain")]
@@ -48,6 +59,16 @@ async def test_asgi():
     assert response.text == "Hello, World!"
 
 
+@pytest.mark.usefixtures("async_environment")
+async def test_asgi_urlencoded_path():
+    async with httpx.AsyncClient(app=echo_path) as client:
+        url = httpx.URL("http://www.example.org/").copy_with(path="/user@example.org")
+        response = await client.get(url)
+
+    assert response.status_code == 200
+    assert response.json() == {"path": "/user@example.org"}
+
+
 @pytest.mark.usefixtures("async_environment")
 async def test_asgi_upload():
     async with httpx.AsyncClient(app=echo_body) as client: