Skip to content
Open
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
4 changes: 2 additions & 2 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
with:
python-version: 3.11
- name: Cache PyPI
uses: actions/cache@v6.1.0
uses: actions/cache@v5.0.5
with:
key: pip-lint-${{ hashFiles('requirements/*.txt') }}
path: ~/.cache/pip
Expand Down Expand Up @@ -158,7 +158,7 @@ jobs:
with:
submodules: true
- name: Cache llhttp generated files
uses: actions/cache@v6.1.0
uses: actions/cache@v5.0.5
id: cache
with:
key: llhttp-${{ hashFiles('vendor/llhttp/package*.json', 'vendor/llhttp/src/**/*') }}
Expand Down
17 changes: 15 additions & 2 deletions aiohttp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,21 @@ def parse_mimetype(mimetype: str) -> MimeType:
for item in parts[1:]:
if not item:
continue
key, _, value = item.partition("=")
params.add(key.lower().strip(), value.strip(' "'))
# Per RFC 9110 section 5.6.5 a parameter is `token "=" token` (or quoted-string)
# and both sides must be non-empty. A bare `;` (already skipped by the
# empty check above) or a `;=value` / `key=` token (empty key) is not a
# valid parameter. Skip it instead of producing `{"": "value"}` which
# downstream callers like StringPayload read with `.get("charset")` and
# silently get an empty key back, defaulting to utf-8 without warning.
key, sep, value = item.partition("=")
if not sep:
# `text/html; charset` is also malformed (no '='). Skip the segment
# rather than treating the whole token as a key with empty value.
continue
key = key.strip()
if not key:
continue
params.add(key.lower(), value.strip(' "'))

fulltype = parts[0].strip().lower()
if fulltype == "*":
Expand Down
14 changes: 10 additions & 4 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,8 @@
helpers.MimeType("application", "rss", "xml", MultiDictProxy(MultiDict())),
),
(
"text/plain;base64",
helpers.MimeType(
"text", "plain", "", MultiDictProxy(MultiDict({"base64": ""}))
),
"text/plain;",
helpers.MimeType("text", "plain", "", MultiDictProxy(MultiDict())),
),
],
)
Expand All @@ -83,6 +81,14 @@ def test_parse_mimetype(mimetype: str, expected: helpers.MimeType) -> None:
assert result == expected


def test_parse_mimetype_skips_empty_param_key_and_missing_equals() -> None:
# Trailing `;` should not insert a `''` key into the params dict
# and the real parameter before it should still parse.
result = helpers.parse_mimetype("application/json; charset=utf-8;")
assert "" not in result.parameters
assert result.parameters.get("charset") == "utf-8"


# ------------------- parse_content_type ------------------------------


Expand Down
Loading