Fix query parameter corruption in base_url with trailing slash enforcement
When a base_url contained query parameters, _enforce_trailing_slash() was appending a slash to the entire raw_path (including the query string), which corrupted the query parameter values. For example: - Before: base_url="https://api.com?data=1" became "https://api.com?data=1/" (query param corrupted to "data=1/" instead of "data=1") - After: base_url="https://api.com?data=1" becomes "https://api.com/?data=1" (query param correctly preserved as "data=1") The fix splits the raw_path into path and query components, adds the trailing slash only to the path portion, then recombines them. Fixes #3614
This commit is contained in:
parent
b5addb64f0
commit
b2adc529e7
@ -232,9 +232,19 @@ class BaseClient:
|
||||
return self._trust_env
|
||||
|
||||
def _enforce_trailing_slash(self, url: URL) -> URL:
|
||||
if url.raw_path.endswith(b"/"):
|
||||
return url
|
||||
return url.copy_with(raw_path=url.raw_path + b"/")
|
||||
# Split raw_path into path and query to avoid corrupting query parameters
|
||||
raw_path = url.raw_path
|
||||
if b"?" in raw_path:
|
||||
# URL has query parameters - only check/add slash to path portion
|
||||
path, query = raw_path.split(b"?", 1)
|
||||
if path.endswith(b"/"):
|
||||
return url
|
||||
return url.copy_with(raw_path=path + b"/?" + query)
|
||||
else:
|
||||
# No query parameters - check/add slash to entire raw_path
|
||||
if raw_path.endswith(b"/"):
|
||||
return url
|
||||
return url.copy_with(raw_path=raw_path + b"/")
|
||||
|
||||
def _get_proxy_map(
|
||||
self, proxy: ProxyTypes | None, allow_env_proxies: bool
|
||||
|
||||
@ -460,3 +460,36 @@ def test_client_decode_text_using_explicit_encoding():
|
||||
assert response.reason_phrase == "OK"
|
||||
assert response.encoding == "ISO-8859-1"
|
||||
assert response.text == text
|
||||
|
||||
|
||||
def test_base_url_with_query_params():
|
||||
"""
|
||||
Test that base_url with query parameters doesn't corrupt the query values.
|
||||
|
||||
Regression test for issue #3614.
|
||||
"""
|
||||
client = httpx.Client(base_url="https://example.com/api?data=1")
|
||||
|
||||
# Query parameter should not be corrupted with trailing slash
|
||||
assert client.base_url.query == b"data=1"
|
||||
assert str(client.base_url) == "https://example.com/api/?data=1"
|
||||
|
||||
|
||||
def test_base_url_with_trailing_slash_and_query():
|
||||
"""
|
||||
Test that base_url with existing trailing slash and query params works correctly.
|
||||
"""
|
||||
client = httpx.Client(base_url="https://example.com/api/?key=value")
|
||||
|
||||
assert client.base_url.query == b"key=value"
|
||||
assert str(client.base_url) == "https://example.com/api/?key=value"
|
||||
|
||||
|
||||
def test_base_url_with_multiple_query_params():
|
||||
"""
|
||||
Test that base_url with multiple query parameters works correctly.
|
||||
"""
|
||||
client = httpx.Client(base_url="https://example.com/api?a=1&b=2&c=3")
|
||||
|
||||
assert client.base_url.query == b"a=1&b=2&c=3"
|
||||
assert str(client.base_url) == "https://example.com/api/?a=1&b=2&c=3"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user