Skip to content

Keep Link header parameter values that contain '=' - #7520

Open
nyxst4ck wants to merge 3 commits into
psf:mainfrom
nyxst4ck:fix/link-header-value-with-equals
Open

Keep Link header parameter values that contain '='#7520
nyxst4ck wants to merge 3 commits into
psf:mainfrom
nyxst4ck:fix/link-header-value-with-equals

Conversation

@nyxst4ck

Copy link
Copy Markdown

Summary

parse_header_links splits each Link header parameter on = with
key, value = param.split("=") (no maxsplit). RFC 8288 permits quoted
parameter values that themselves contain = (pagination/cursor tokens,
base64 values, signed URLs, etc.). Such a value produces 3+ parts and raises
ValueError: too many values to unpack, which the bare except ValueError: break swallows — silently dropping that parameter and every parameter after
it
in the link.

>>> import requests
>>> r = requests.Response()
>>> r.headers["Link"] = '<https://api.example.com/items>; rel="next"; title="a=b"'
>>> r.links
{'next': {'url': 'https://api.example.com/items', 'rel': 'next'}}   # 'title' lost

Fix

param.split("=")param.split("=", 1) in parse_header_links, so the value
keeps its = and following parameters are preserved.

Tests

Added a test_parse_header_links parametrization with a value containing =
(title="a=b" followed by rel="next"). It fails on main (both title and
the trailing rel are dropped) and passes with the fix. tests/test_utils.py::test_parse_header_links
is green (6 passed); ruff check/ruff format clean.

No existing issue tracked this; the bug is long-standing.

@DTiming24

This comment was marked as low quality.

nyxst4ck added 2 commits July 16, 2026 18:26
parse_header_links split each parameter on '=' without a maxsplit, so a quoted
value containing '=' (allowed by RFC 8288) produced 3+ parts and raised
ValueError. The bare 'except ValueError: break' then silently dropped that
parameter and every parameter after it in the link.

Use split('=', 1) so the value keeps its '=' and later parameters survive.
@nyxst4ck

Copy link
Copy Markdown
Author

Added the quoted semicolon regression and a quote-aware parameter splitter, then rebased onto current main. tests/test_utils.py: 230 passed, 1 skipped. Full suite: 632 passed, 3 skipped; one unrelated Windows TLS test could not find tests/certs/valid/ca/ca.crt.

@nyxst4ck
nyxst4ck force-pushed the fix/link-header-value-with-equals branch from 028edad to b536520 Compare July 16, 2026 21:32
@Sanjays2402

Copy link
Copy Markdown

the inner param split is quote-aware now, but the outer re.split(", *<", value) that separates multiple links still isn't — a comma inside a quoted param value splits one link into two. parse_header_links('<http://x/a>; title="a,<b"; rel="next"') comes back as two bogus entries. RFC 8288 quoted-strings can contain commas, so it's the same input class you're fixing here.

Samielakkad

This comment was marked as resolved.

parse_header_links split individual link entries on ", *<" without
regard for quoting, so a quoted parameter value containing a comma
immediately followed by '<' (RFC 8288 quoted-strings may contain
commas) was mistaken for the separator between two links, corrupting
the entry into two bogus ones.

Reuse the same quote-tracking approach as the parameter splitter for
the entry splitter.
@nyxst4ck

Copy link
Copy Markdown
Author

Good catch, thanks — that's a real gap. Fixed by making the entry splitter quote-aware too (same state-machine approach as _parse_header_links_params): a , immediately followed by < no longer splits while inside a quoted value.

Added '<...front.jpeg>; title="a,<b"; rel="next"' as a regression case, plus one with a real second link entry after it to prove the split still fires correctly. tests/test_utils.py -k parse_header_links: 9/9 passed. Full test_utils.py: 232 passed, 1 skipped (unrelated). Ruff check/format clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mass-automation-pr This PR was created from an account spamming large projects with "fixes".

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants