Skip to content

Commit 6693f71

Browse files
Use fallback request context for transport request errors
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent ff3b02b commit 6693f71

File tree

4 files changed

+95
-12
lines changed

4 files changed

+95
-12
lines changed

hyperbrowser/transport/async_transport.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
from hyperbrowser.header_utils import merge_headers
77
from hyperbrowser.version import __version__
88
from .base import APIResponse, AsyncTransportStrategy
9-
from .error_utils import extract_error_message, extract_request_error_context
9+
from .error_utils import (
10+
extract_error_message,
11+
extract_request_error_context,
12+
format_request_failure_message,
13+
)
1014

1115

1216
class AsyncTransport(AsyncTransportStrategy):
@@ -81,7 +85,10 @@ async def post(
8185
return await self._handle_response(response)
8286
except httpx.RequestError as e:
8387
raise HyperbrowserError(
84-
f"POST request to {url} failed", original_error=e
88+
format_request_failure_message(
89+
e, fallback_method="POST", fallback_url=url
90+
),
91+
original_error=e,
8592
) from e
8693
except HyperbrowserError:
8794
raise
@@ -102,7 +109,10 @@ async def get(
102109
return await self._handle_response(response)
103110
except httpx.RequestError as e:
104111
raise HyperbrowserError(
105-
f"GET request to {url} failed", original_error=e
112+
format_request_failure_message(
113+
e, fallback_method="GET", fallback_url=url
114+
),
115+
original_error=e,
106116
) from e
107117
except HyperbrowserError:
108118
raise
@@ -117,7 +127,10 @@ async def put(self, url: str, data: Optional[dict] = None) -> APIResponse:
117127
return await self._handle_response(response)
118128
except httpx.RequestError as e:
119129
raise HyperbrowserError(
120-
f"PUT request to {url} failed", original_error=e
130+
format_request_failure_message(
131+
e, fallback_method="PUT", fallback_url=url
132+
),
133+
original_error=e,
121134
) from e
122135
except HyperbrowserError:
123136
raise
@@ -132,7 +145,10 @@ async def delete(self, url: str) -> APIResponse:
132145
return await self._handle_response(response)
133146
except httpx.RequestError as e:
134147
raise HyperbrowserError(
135-
f"DELETE request to {url} failed", original_error=e
148+
format_request_failure_message(
149+
e, fallback_method="DELETE", fallback_url=url
150+
),
151+
original_error=e,
136152
) from e
137153
except HyperbrowserError:
138154
raise

hyperbrowser/transport/error_utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,14 @@ def extract_request_error_context(error: httpx.RequestError) -> tuple[str, str]:
4343
if request is None:
4444
return "UNKNOWN", "unknown URL"
4545
return request.method, str(request.url)
46+
47+
48+
def format_request_failure_message(
49+
error: httpx.RequestError, *, fallback_method: str, fallback_url: str
50+
) -> str:
51+
request_method, request_url = extract_request_error_context(error)
52+
effective_method = (
53+
request_method if request_method != "UNKNOWN" else fallback_method
54+
)
55+
effective_url = request_url if request_url != "unknown URL" else fallback_url
56+
return f"Request {effective_method} {effective_url} failed"

hyperbrowser/transport/sync.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
from hyperbrowser.header_utils import merge_headers
77
from hyperbrowser.version import __version__
88
from .base import APIResponse, SyncTransportStrategy
9-
from .error_utils import extract_error_message, extract_request_error_context
9+
from .error_utils import (
10+
extract_error_message,
11+
extract_request_error_context,
12+
format_request_failure_message,
13+
)
1014

1115

1216
class SyncTransport(SyncTransportStrategy):
@@ -72,7 +76,10 @@ def post(
7276
return self._handle_response(response)
7377
except httpx.RequestError as e:
7478
raise HyperbrowserError(
75-
f"POST request to {url} failed", original_error=e
79+
format_request_failure_message(
80+
e, fallback_method="POST", fallback_url=url
81+
),
82+
original_error=e,
7683
) from e
7784
except HyperbrowserError:
7885
raise
@@ -93,7 +100,10 @@ def get(
93100
return self._handle_response(response)
94101
except httpx.RequestError as e:
95102
raise HyperbrowserError(
96-
f"GET request to {url} failed", original_error=e
103+
format_request_failure_message(
104+
e, fallback_method="GET", fallback_url=url
105+
),
106+
original_error=e,
97107
) from e
98108
except HyperbrowserError:
99109
raise
@@ -108,7 +118,10 @@ def put(self, url: str, data: Optional[dict] = None) -> APIResponse:
108118
return self._handle_response(response)
109119
except httpx.RequestError as e:
110120
raise HyperbrowserError(
111-
f"PUT request to {url} failed", original_error=e
121+
format_request_failure_message(
122+
e, fallback_method="PUT", fallback_url=url
123+
),
124+
original_error=e,
112125
) from e
113126
except HyperbrowserError:
114127
raise
@@ -123,7 +136,10 @@ def delete(self, url: str) -> APIResponse:
123136
return self._handle_response(response)
124137
except httpx.RequestError as e:
125138
raise HyperbrowserError(
126-
f"DELETE request to {url} failed", original_error=e
139+
format_request_failure_message(
140+
e, fallback_method="DELETE", fallback_url=url
141+
),
142+
original_error=e,
127143
) from e
128144
except HyperbrowserError:
129145
raise

tests/test_transport_response_handling.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ def failing_post(*args, **kwargs):
222222
transport.client.post = failing_post # type: ignore[assignment]
223223
try:
224224
with pytest.raises(
225-
HyperbrowserError, match="POST request to https://example.com/post failed"
225+
HyperbrowserError, match="Request POST https://example.com/post failed"
226226
):
227227
transport.post("https://example.com/post", data={"ok": True})
228228
finally:
@@ -261,7 +261,7 @@ async def failing_get(*args, **kwargs):
261261
try:
262262
with pytest.raises(
263263
HyperbrowserError,
264-
match="GET request to https://example.com/get failed",
264+
match="Request GET https://example.com/get failed",
265265
):
266266
await transport.get("https://example.com/get")
267267
finally:
@@ -310,3 +310,43 @@ async def failing_put(*args, **kwargs):
310310
await transport.close()
311311

312312
asyncio.run(run())
313+
314+
315+
def test_sync_transport_request_error_without_request_uses_fallback_url():
316+
transport = SyncTransport(api_key="test-key")
317+
original_get = transport.client.get
318+
319+
def failing_get(*args, **kwargs):
320+
raise httpx.RequestError("network down")
321+
322+
transport.client.get = failing_get # type: ignore[assignment]
323+
try:
324+
with pytest.raises(
325+
HyperbrowserError, match="Request GET https://example.com/fallback failed"
326+
):
327+
transport.get("https://example.com/fallback")
328+
finally:
329+
transport.client.get = original_get # type: ignore[assignment]
330+
transport.close()
331+
332+
333+
def test_async_transport_request_error_without_request_uses_fallback_url():
334+
async def run() -> None:
335+
transport = AsyncTransport(api_key="test-key")
336+
original_delete = transport.client.delete
337+
338+
async def failing_delete(*args, **kwargs):
339+
raise httpx.RequestError("network down")
340+
341+
transport.client.delete = failing_delete # type: ignore[assignment]
342+
try:
343+
with pytest.raises(
344+
HyperbrowserError,
345+
match="Request DELETE https://example.com/fallback failed",
346+
):
347+
await transport.delete("https://example.com/fallback")
348+
finally:
349+
transport.client.delete = original_delete # type: ignore[assignment]
350+
await transport.close()
351+
352+
asyncio.run(run())

0 commit comments

Comments
 (0)