From c599730b9ecc4bf91194fd5acfef5766d92409c3 Mon Sep 17 00:00:00 2001 From: Zo Bot Date: Fri, 3 Jul 2026 23:53:15 +0000 Subject: [PATCH] parse_mimetype: skip whitespace-only segments after a semicolon Trailing ';' followed by whitespace (e.g. "text/html; ") inserted a spurious empty-key parameter in the parsed parameters dict, while a bare trailing ';' was already correctly skipped. The check is now 'if not item.strip()' so whitespace-only segments are also skipped. --- CHANGES/13009.bugfix.rst | 1 + aiohttp/helpers.py | 2 +- tests/test_helpers.py | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 CHANGES/13009.bugfix.rst diff --git a/CHANGES/13009.bugfix.rst b/CHANGES/13009.bugfix.rst new file mode 100644 index 00000000000..f7faff672f0 --- /dev/null +++ b/CHANGES/13009.bugfix.rst @@ -0,0 +1 @@ +Fixed :py:func:`~aiohttp.helpers.parse_mimetype` inserting a spurious empty-key diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index 2fa8a19b6a7..65bc269e1da 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -332,7 +332,7 @@ def parse_mimetype(mimetype: str) -> MimeType: parts = mimetype.split(";") params: MultiDict[str] = MultiDict() for item in parts[1:]: - if not item: + if not item.strip(): continue key, _, value = item.partition("=") params.add(key.lower().strip(), value.strip(' "')) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index a499746607a..7f05c144385 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -83,6 +83,33 @@ def test_parse_mimetype(mimetype: str, expected: helpers.MimeType) -> None: assert result == expected +@pytest.mark.parametrize( + "mimetype", + [ + "text/html; ", + "text/html; ", + "text/html;\t", + "text/html; \t", + "text/html; charset=utf-8; ", + "text/html; charset=utf-8;\t\t", + ], +) +def test_parse_mimetype_skips_whitespace_only_segments( + mimetype: str, +) -> None: + # https://github.com/aio-libs/aiohttp/issues/13009 + # A trailing ';' followed by whitespace (e.g. 'text/html; ') was being + # treated as a parameter with an empty key, producing {'': ''} in the + # parsed parameters. RFC 2045 says whitespace-only segments after a ';' + # are not valid parameters; a bare trailing ';' was already skipped + # because it becomes an empty string, but 'text/html; ' was truthy + # and slipped through. + result = helpers.parse_mimetype(mimetype) + assert "" not in result.parameters + if "charset=utf-8" in mimetype: + assert result.parameters.get("charset") == "utf-8" + + # ------------------- parse_content_type ------------------------------