Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/13099.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed ``BaseRequest.text()`` and ``application/x-www-form-urlencoded`` request parsing to return HTTP 415 when body bytes fail to decode with the default charset -- by :user:`cyphercodes`.
8 changes: 4 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ To get something from the web:
async def main():

async with aiohttp.ClientSession() as session:
async with session.get('http://python.org') as response:
async with session.get('https://python.org') as response:

print("Status:", response.status)
print("Content-type:", response.headers['content-type'])
Expand Down Expand Up @@ -134,11 +134,11 @@ External links
==============

* `Third party libraries
<http://aiohttp.readthedocs.io/en/latest/third_party.html>`_
<https://aiohttp.readthedocs.io/en/latest/third_party.html>`_
* `Built with aiohttp
<http://aiohttp.readthedocs.io/en/latest/built_with.html>`_
<https://aiohttp.readthedocs.io/en/latest/built_with.html>`_
* `Powered by aiohttp
<http://aiohttp.readthedocs.io/en/latest/powered_by.html>`_
<https://aiohttp.readthedocs.io/en/latest/powered_by.html>`_

Feel free to make a Pull Request for adding your link to these pages!

Expand Down
4 changes: 2 additions & 2 deletions aiohttp/web_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ async def text(self) -> str:
encoding = self.charset or "utf-8"
try:
return bytes_body.decode(encoding)
except LookupError:
except (LookupError, UnicodeDecodeError):
raise HTTPUnsupportedMediaType()

async def json(
Expand Down Expand Up @@ -790,7 +790,7 @@ async def post(self) -> "MultiDictProxy[str | bytes | FileField]":
bytes_query = data.rstrip()
try:
query = bytes_query.decode(charset)
except LookupError:
except (LookupError, UnicodeDecodeError):
raise HTTPUnsupportedMediaType()
out.extend(
parse_qsl(qs=query, keep_blank_values=True, encoding=charset)
Expand Down
34 changes: 34 additions & 0 deletions tests/test_web_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,22 @@ async def test_request_with_wrong_content_type_encoding(protocol: BaseProtocol)
assert err.value.status_code == 415


async def test_request_text_with_invalid_default_encoding(
protocol: BaseProtocol,
) -> None:
payload = StreamReader(
protocol, DEFAULT_CHUNK_SIZE, loop=asyncio.get_running_loop()
)
payload.feed_data(b"\xff")
payload.feed_eof()
headers = {"Content-Type": "text/html"}
req = make_mocked_request("POST", "/", payload=payload, headers=headers)

with pytest.raises(web.HTTPUnsupportedMediaType) as err:
await req.text()
assert err.value.status_code == 415


async def test_make_too_big_request_same_size_to_max(protocol: BaseProtocol) -> None:
payload = StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
large_file = 1024**2 * b"x"
Expand Down Expand Up @@ -977,6 +993,24 @@ async def test_multipart_formdata(protocol: BaseProtocol) -> None:
assert dict(result) == {"a": "b", "c": "d"}


async def test_urlencoded_form_with_invalid_default_encoding(
protocol: BaseProtocol,
) -> None:
payload = StreamReader(
protocol, DEFAULT_CHUNK_SIZE, loop=asyncio.get_running_loop()
)
payload.feed_data(b"a=1&b=\xff")
payload.feed_eof()
headers = {
"Content-Type": "application/x-www-form-urlencoded",
}
req = make_mocked_request("POST", "/", payload=payload, headers=headers)

with pytest.raises(web.HTTPUnsupportedMediaType) as err:
await req.post()
assert err.value.status_code == 415


async def test_multipart_formdata_field_missing_name(protocol: BaseProtocol) -> None:
# Ensure ValueError is raised when Content-Disposition has no name
payload = StreamReader(
Expand Down
Loading