Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ASGITransport path escaping #1307

Merged
merged 1 commit into from Sep 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion httpx/_transports/asgi.py
@@ -1,4 +1,5 @@
from typing import TYPE_CHECKING, Callable, List, Optional, Tuple, Union
from urllib.parse import unquote

import httpcore
import sniffio
Expand Down Expand Up @@ -88,7 +89,7 @@ async def arequest(
"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,
Expand Down
21 changes: 21 additions & 0 deletions tests/test_asgi.py
@@ -1,3 +1,5 @@
import json

import pytest

import httpx
Expand All @@ -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")]
Expand Down Expand Up @@ -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:
Expand Down