Stricter charset handling and escaping of request URLs (#2710)
Co-authored-by: L. Karkkainen <tronic@users.noreply.github.com>
This commit is contained in:
@@ -11,7 +11,7 @@ from aioquic.quic.events import ProtocolNegotiated
|
||||
from sanic import Request, Sanic
|
||||
from sanic.compat import Header
|
||||
from sanic.config import DEFAULT_CONFIG
|
||||
from sanic.exceptions import PayloadTooLarge
|
||||
from sanic.exceptions import BadRequest, PayloadTooLarge
|
||||
from sanic.http.constants import Stage
|
||||
from sanic.http.http3 import Http3, HTTPReceiver
|
||||
from sanic.models.server_types import ConnInfo
|
||||
@@ -292,3 +292,48 @@ def test_request_conn_info(app):
|
||||
receiver = http3.get_receiver_by_stream_id(1)
|
||||
|
||||
assert isinstance(receiver.request.conn_info, ConnInfo)
|
||||
|
||||
|
||||
def test_request_header_encoding(app):
|
||||
protocol = generate_protocol(app)
|
||||
http3 = Http3(protocol, protocol.transmit)
|
||||
with pytest.raises(BadRequest) as exc_info:
|
||||
http3.http_event_received(
|
||||
HeadersReceived(
|
||||
[
|
||||
(b":method", b"GET"),
|
||||
(b":path", b"/location"),
|
||||
(b":scheme", b"https"),
|
||||
(b":authority", b"localhost:8443"),
|
||||
("foo\u00A0".encode(), b"bar"),
|
||||
],
|
||||
1,
|
||||
False,
|
||||
)
|
||||
)
|
||||
assert exc_info.value.status_code == 400
|
||||
assert (
|
||||
str(exc_info.value)
|
||||
== "Header names may only contain US-ASCII characters."
|
||||
)
|
||||
|
||||
|
||||
def test_request_url_encoding(app):
|
||||
protocol = generate_protocol(app)
|
||||
http3 = Http3(protocol, protocol.transmit)
|
||||
with pytest.raises(BadRequest) as exc_info:
|
||||
http3.http_event_received(
|
||||
HeadersReceived(
|
||||
[
|
||||
(b":method", b"GET"),
|
||||
(b":path", b"/location\xA0"),
|
||||
(b":scheme", b"https"),
|
||||
(b":authority", b"localhost:8443"),
|
||||
(b"foo", b"bar"),
|
||||
],
|
||||
1,
|
||||
False,
|
||||
)
|
||||
)
|
||||
assert exc_info.value.status_code == 400
|
||||
assert str(exc_info.value) == "URL may only contain US-ASCII characters."
|
||||
|
||||
@@ -652,3 +652,17 @@ async def test_asgi_headers_decoding(app: Sanic, monkeypatch: MonkeyPatch):
|
||||
|
||||
_, response = await app.asgi_client.get("/", headers={"Test-Header": "😅"})
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_asgi_url_decoding(app):
|
||||
@app.get("/dir/<name>", unquote=True)
|
||||
def _request(request: Request, name):
|
||||
return text(name)
|
||||
|
||||
# 2F should not become a path separator (unquoted later)
|
||||
_, response = await app.asgi_client.get("/dir/some%2Fpath")
|
||||
assert response.text == "some/path"
|
||||
|
||||
_, response = await app.asgi_client.get("/dir/some%F0%9F%98%80path")
|
||||
assert response.text == "some😀path"
|
||||
|
||||
@@ -98,3 +98,17 @@ def test_transfer_chunked(client):
|
||||
data = stdjson.loads(body)
|
||||
|
||||
assert data == ["foo", "bar"]
|
||||
|
||||
|
||||
def test_url_encoding(client):
|
||||
client.send(
|
||||
"""
|
||||
GET /invalid\xA0url HTTP/1.1
|
||||
|
||||
"""
|
||||
)
|
||||
response = client.recv()
|
||||
headers, body = response.rsplit(b"\r\n\r\n", 1)
|
||||
|
||||
assert b"400 Bad Request" in headers
|
||||
assert b"URL may only contain US-ASCII characters." in body
|
||||
|
||||
Reference in New Issue
Block a user