Skip to content

Commit 02cbe1f

Browse files
Handle /api query paths without duplicate prefixing
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 336277e commit 02cbe1f

2 files changed

Lines changed: 26 additions & 6 deletions

File tree

hyperbrowser/client/base.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,27 @@ def _build_url(self, path: str) -> str:
8282
if parsed_path.fragment:
8383
raise HyperbrowserError("path must not include URL fragments")
8484
normalized_path = f"/{stripped_path.lstrip('/')}"
85+
normalized_parts = urlparse(normalized_path)
86+
normalized_path_only = normalized_parts.path
87+
normalized_query_suffix = (
88+
f"?{normalized_parts.query}" if normalized_parts.query else ""
89+
)
8590
base_has_api_suffix = (
8691
urlparse(self.config.base_url).path.rstrip("/").endswith("/api")
8792
)
8893

89-
if normalized_path == "/api" or normalized_path.startswith("/api/"):
94+
if normalized_path_only == "/api" or normalized_path_only.startswith("/api/"):
9095
if base_has_api_suffix:
91-
deduped_path = normalized_path[len("/api") :]
92-
return f"{self.config.base_url}{deduped_path}"
93-
return f"{self.config.base_url}{normalized_path}"
96+
deduped_path = normalized_path_only[len("/api") :]
97+
return f"{self.config.base_url}{deduped_path}{normalized_query_suffix}"
98+
return (
99+
f"{self.config.base_url}{normalized_path_only}{normalized_query_suffix}"
100+
)
94101

95102
if base_has_api_suffix:
96-
return f"{self.config.base_url}{normalized_path}"
97-
return f"{self.config.base_url}/api{normalized_path}"
103+
return (
104+
f"{self.config.base_url}{normalized_path_only}{normalized_query_suffix}"
105+
)
106+
return (
107+
f"{self.config.base_url}/api{normalized_path_only}{normalized_query_suffix}"
108+
)

tests/test_url_building.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ def test_client_build_url_normalizes_leading_slash():
2020
client._build_url("api/session")
2121
== "https://api.hyperbrowser.ai/api/session"
2222
)
23+
assert (
24+
client._build_url("/api?foo=bar")
25+
== "https://api.hyperbrowser.ai/api?foo=bar"
26+
)
2327
assert (
2428
client._build_url("//api/session")
2529
== "https://api.hyperbrowser.ai/api/session"
@@ -49,6 +53,7 @@ def test_client_build_url_avoids_duplicate_api_when_base_url_already_has_api():
4953
try:
5054
assert client._build_url("/session") == "https://example.local/api/session"
5155
assert client._build_url("/api/session") == "https://example.local/api/session"
56+
assert client._build_url("/api?foo=bar") == "https://example.local/api?foo=bar"
5257
finally:
5358
client.close()
5459

@@ -116,5 +121,9 @@ def test_client_build_url_allows_query_values_containing_absolute_urls():
116121
client._build_url("/web/fetch?target=https://example.com")
117122
== "https://api.hyperbrowser.ai/api/web/fetch?target=https://example.com"
118123
)
124+
assert (
125+
client._build_url("/session?foo=bar")
126+
== "https://api.hyperbrowser.ai/api/session?foo=bar"
127+
)
119128
finally:
120129
client.close()

0 commit comments

Comments
 (0)