Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions httpx/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,15 @@ def trust_env(self) -> bool:
return self._trust_env

def _enforce_trailing_slash(self, url: URL) -> URL:
if url.raw_path.endswith(b"/"):
raw_path = url.raw_path
if b"?" in raw_path:
path_part, query_part = raw_path.split(b"?", 1)
if path_part.endswith(b"/"):
return url
return url.copy_with(raw_path=path_part + b"/?" + query_part)
if raw_path.endswith(b"/"):
return url
return url.copy_with(raw_path=url.raw_path + b"/")
return url.copy_with(raw_path=raw_path + b"/")

def _get_proxy_map(
self, proxy: ProxyTypes | None, allow_env_proxies: bool
Expand Down Expand Up @@ -406,7 +412,19 @@ def _merge_url(self, url: URL | str) -> URL:
# URL('https://www.example.com/subpath/')
# >>> client.build_request("GET", "/path").url
# URL('https://www.example.com/subpath/path')
merge_raw_path = self.base_url.raw_path + merge_url.raw_path.lstrip(b"/")
base_raw_path = self.base_url.raw_path
if b"?" in base_raw_path:
base_path, base_query = base_raw_path.split(b"?", 1)
merge_raw_path = (
base_path
+ merge_url.raw_path.lstrip(b"/")
+ b"?"
+ base_query
)
else:
merge_raw_path = (
base_raw_path + merge_url.raw_path.lstrip(b"/")
)
return self.base_url.copy_with(raw_path=merge_raw_path)
return merge_url

Expand Down
11 changes: 11 additions & 0 deletions tests/client/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,17 @@ def test_merge_relative_url_with_encoded_slashes():
assert request.url == "https://www.example.com/base%2Fpath/testing"


def test_merge_url_with_base_url_query_params():
# https://github.com/encode/httpx/issues/3614
client = httpx.Client(base_url="https://www.example.com/get?data=1")

request = client.build_request("GET", "")
assert str(request.url) == "https://www.example.com/get/?data=1"

request = client.build_request("GET", "/users")
assert str(request.url) == "https://www.example.com/get/users?data=1"


def test_context_managed_transport():
class Transport(httpx.BaseTransport):
def __init__(self) -> None:
Expand Down