`base_url` with a query string produces malformed request URLs
Maintainers usually reply within 1 day
@mohsinaliwork686-rgb is already working on this.
Since Oct 26, 2026.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 52/100
Research direction
Start in _client.py by reading _enforce_trailing_slash and _merge_url, focusing on their use of raw_path when base_url contains a query. Reproduce both examples, then confirm with maintainers whether query-bearing base URLs should be rejected or supported; done means tests cover both relative requests and params= without malformed or missing paths.
Written by the indexing model from the issue text.
Description
A base_url that contains a query string is not rejected, but every relative request built from it has a broken URL. Reproduced on httpx2 2.13.1:
import httpx2
client = httpx2.Client(base_url="https://example.com/api?key=k")
print(repr(client.base_url))
# URL('https://example.com/api?key=k/')
print(client.build_request("GET", "items").url)
# https://example.com/api?key=k/items
print(client.build_request("GET", "items", params={"b": "2"}).url)
# https://example.com/api?b=2
In the first request the path ends up inside the query (key becomes k/items). In the second the path items is lost entirely. No error is raised in either case, so the request silently goes to the wrong URL.
Cause
Both steps operate on raw_path, which includes the query:
_enforce_trailing_slash(_client.py) appends/tourl.raw_path, so the slash lands after the query:/api?key=k/._merge_urlbuildsself.base_url.raw_path + merge_url.raw_path.lstrip(b"/"), so the request path is appended after the query too.
The second case then loses the path because params= replaces the whole query (#905), and the query now holds the path.
Possible fixes
- Reject a
base_urlwith a query string in thebase_urlsetter, with a message pointing toparams=. - Support it: operate on
pathrather thanraw_pathin both places and merge the base query into the request's params.
- Dominant language
- Python
- Stars
- 1.6k
- Forks
- 103
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 25
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from pydantic/httpx2
-
Please revert aiter_bytes signature to AsyncIteratorMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
pydantic/httpx2#1158 · 2 comments ·
Maintainers usually reply within 1 day
-
Export AutoBackendMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 1/5 Under an hour Newbie friendliness 92/100
pydantic/httpx2#1131 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 1 day
-
Mention header name error message for invalid header encodingsMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
pydantic/httpx2#864 · 3 comments ·
Maintainers usually reply within 1 day
-
Support DigestAuth with "x-www-authenticate" in first response headerPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
Similar issues
-
Email validation accepts a trailing newlinePossibly taken @marcello-pichini claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
dbt-labs/spark-utils#51 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
bug frontend
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
vendrabuck/HERD#1419 ·
Maintainers usually reply within 1 day