diff --git a/httpx/_client.py b/httpx/_client.py index 13cd933673..49f928ddf7 100644 --- a/httpx/_client.py +++ b/httpx/_client.py @@ -232,9 +232,19 @@ def trust_env(self) -> bool: 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 diff --git a/tests/client/test_client.py b/tests/client/test_client.py index 657839018a..9e7a601c5b 100644 --- a/tests/client/test_client.py +++ b/tests/client/test_client.py @@ -460,3 +460,36 @@ def cp1252_but_no_content_type(request): 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"