Skip to content

Commit 0afddcf

Browse files
Validate and copy client header configuration safely
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent fe8e425 commit 0afddcf

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

hyperbrowser/config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ def __post_init__(self) -> None:
1818
raise HyperbrowserError("api_key must be a string")
1919
if not isinstance(self.base_url, str):
2020
raise HyperbrowserError("base_url must be a string")
21+
if self.headers is not None and not isinstance(self.headers, dict):
22+
raise HyperbrowserError("headers must be a dictionary of string pairs")
2123
self.api_key = self.api_key.strip()
2224
self.base_url = self.base_url.strip().rstrip("/")
2325
if not self.base_url:
@@ -29,6 +31,15 @@ def __post_init__(self) -> None:
2931
raise HyperbrowserError(
3032
"base_url must start with 'https://' or 'http://'"
3133
)
34+
if self.headers is not None:
35+
normalized_headers: Dict[str, str] = {}
36+
for key, value in self.headers.items():
37+
if not isinstance(key, str) or not isinstance(value, str):
38+
raise HyperbrowserError(
39+
"headers must be a dictionary of string pairs"
40+
)
41+
normalized_headers[key] = value
42+
self.headers = normalized_headers
3243

3344
@classmethod
3445
def from_env(cls) -> "ClientConfig":

tests/test_config.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,27 @@ def test_client_config_rejects_non_string_values():
5959
with pytest.raises(HyperbrowserError, match="base_url must be a string"):
6060
ClientConfig(api_key="test-key", base_url=None) # type: ignore[arg-type]
6161

62+
with pytest.raises(HyperbrowserError, match="headers must be a dictionary"):
63+
ClientConfig(api_key="test-key", headers="x=1") # type: ignore[arg-type]
64+
6265

6366
def test_client_config_rejects_empty_or_invalid_base_url():
6467
with pytest.raises(HyperbrowserError, match="base_url must not be empty"):
6568
ClientConfig(api_key="test-key", base_url=" ")
6669

6770
with pytest.raises(HyperbrowserError, match="base_url must start with"):
6871
ClientConfig(api_key="test-key", base_url="api.hyperbrowser.ai")
72+
73+
74+
def test_client_config_normalizes_headers_to_internal_copy():
75+
headers = {"X-Correlation-Id": "abc123"}
76+
config = ClientConfig(api_key="test-key", headers=headers)
77+
78+
headers["X-Correlation-Id"] = "changed"
79+
80+
assert config.headers == {"X-Correlation-Id": "abc123"}
81+
82+
83+
def test_client_config_rejects_non_string_header_pairs():
84+
with pytest.raises(HyperbrowserError, match="headers must be a dictionary"):
85+
ClientConfig(api_key="test-key", headers={"X-Correlation-Id": 123}) # type: ignore[dict-item]

0 commit comments

Comments
 (0)