Skip to content

fix!: append params after the URL's own query and keep its bytes - #156

Merged
lesnik512 merged 2 commits into
mainfrom
fix/append-url-query
Oct 4, 2026
Merged

lesnik512 merged 2 commits into
mainfrom
fix/append-url-query

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Changes how a URL's own query string combines with params, to match requests and the pending upstream fix (pydantic/httpx2#966). It also stops httpware from re-encoding that query string.

Behaviour change

params (client-level, then per-request) are now appended after the URL's query. Duplicate keys are kept instead of overridden.

URL params client params Before After
?a=1&b=1 b=2 - a=1&b=2 a=1&b=1&b=2
?a=1&c=1 b=2 c=3 c=1&a=1&b=2 a=1&c=1&c=3&b=2
?a=1 - c=3 c=3&a=1 a=1&c=3

Code that put a key in the URL and relied on params to replace it will now send the key twice. Release notes should call this out.

Bug fixed: the URL's query was re-encoded

Before, when any params applied, the URL's query was parsed and rebuilt: ?q=a%20b went out as q=a+b and ?flag as flag=. That can break signed URLs and servers that are strict about encoding. Now the original bytes are sent unchanged (new test case url-query-bytes-kept).

How

httpx2 sends params through str(QueryParams(...)), which re-encodes them, so nothing passed as params keeps the URL's original bytes. _build_request replaces _merge_url_query. It strips the URL's query, lets httpx2 build the request, then puts the original query bytes back in front of whatever query httpx2 built.

To route the uncapped stream() path through _build_request, it now uses _stream / _stream_async. These mirror httpx2.Client.stream: build_request, then send(stream=True), then close on exit. The capped path already worked this way. The request is still built lazily, inside the exception mapper.

Relation to #146

tests/test_url_query_merge.py now matches upstream behaviour. Against pydantic/httpx2#966 (2631c38) with _build_request stubbed to a pass-through, all 50 tests pass. Against httpx2 2.13.1 with the same stub, 43 fail, so the workaround is still needed until a release includes the fix. Once one does, #146 is a plain deletion with no behaviour change.

Verification

just lint-ci passes, and just test-ci passes 1007 tests at 100% coverage.

@lesnik512
lesnik512 merged commit 5d94ba2 into main Oct 4, 2026
13 checks passed
@lesnik512
lesnik512 deleted the fix/append-url-query branch October 4, 2026 08:29
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.

1 participant