Skip to content

Commit ff3b02b

Browse files
Normalize runtime base URL values in URL builder
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 42c3230 commit ff3b02b

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

hyperbrowser/client/base.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,13 @@ def _build_url(self, path: str) -> str:
8787
normalized_query_suffix = (
8888
f"?{normalized_parts.query}" if normalized_parts.query else ""
8989
)
90-
parsed_base_url = urlparse(self.config.base_url)
90+
if not isinstance(self.config.base_url, str):
91+
raise HyperbrowserError("base_url must be a string")
92+
normalized_base_url = self.config.base_url.strip().rstrip("/")
93+
if not normalized_base_url:
94+
raise HyperbrowserError("base_url must not be empty")
95+
96+
parsed_base_url = urlparse(normalized_base_url)
9197
if (
9298
parsed_base_url.scheme not in {"https", "http"}
9399
or not parsed_base_url.netloc
@@ -104,15 +110,15 @@ def _build_url(self, path: str) -> str:
104110
if normalized_path_only == "/api" or normalized_path_only.startswith("/api/"):
105111
if base_has_api_suffix:
106112
deduped_path = normalized_path_only[len("/api") :]
107-
return f"{self.config.base_url}{deduped_path}{normalized_query_suffix}"
113+
return f"{normalized_base_url}{deduped_path}{normalized_query_suffix}"
108114
return (
109-
f"{self.config.base_url}{normalized_path_only}{normalized_query_suffix}"
115+
f"{normalized_base_url}{normalized_path_only}{normalized_query_suffix}"
110116
)
111117

112118
if base_has_api_suffix:
113119
return (
114-
f"{self.config.base_url}{normalized_path_only}{normalized_query_suffix}"
120+
f"{normalized_base_url}{normalized_path_only}{normalized_query_suffix}"
115121
)
116122
return (
117-
f"{self.config.base_url}/api{normalized_path_only}{normalized_query_suffix}"
123+
f"{normalized_base_url}/api{normalized_path_only}{normalized_query_suffix}"
118124
)

tests/test_url_building.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ def test_client_build_url_rejects_runtime_invalid_base_url_changes():
9797
HyperbrowserError, match="must not include query parameters"
9898
):
9999
client._build_url("/session")
100+
101+
client.config.base_url = " "
102+
with pytest.raises(HyperbrowserError, match="base_url must not be empty"):
103+
client._build_url("/session")
104+
105+
client.config.base_url = 123 # type: ignore[assignment]
106+
with pytest.raises(HyperbrowserError, match="base_url must be a string"):
107+
client._build_url("/session")
100108
finally:
101109
client.close()
102110

@@ -143,3 +151,15 @@ def test_client_build_url_allows_query_values_containing_absolute_urls():
143151
)
144152
finally:
145153
client.close()
154+
155+
156+
def test_client_build_url_normalizes_runtime_trailing_slashes():
157+
client = Hyperbrowser(config=ClientConfig(api_key="test-key"))
158+
try:
159+
client.config.base_url = "https://example.local/"
160+
assert client._build_url("/session") == "https://example.local/api/session"
161+
162+
client.config.base_url = "https://example.local/api/"
163+
assert client._build_url("/session") == "https://example.local/api/session"
164+
finally:
165+
client.close()

0 commit comments

Comments
 (0)