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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants