Skip to content

Commit 6c2809e

Browse files
Support bytes response text in transport fallback extraction
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent b313841 commit 6c2809e

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

hyperbrowser/transport/error_utils.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,17 @@ def _truncate_error_message(message: str) -> str:
142142
return f"{sanitized_message[:_MAX_ERROR_MESSAGE_LENGTH]}... (truncated)"
143143

144144

145+
def _normalize_response_text_for_error_message(response_text: Any) -> str:
146+
if isinstance(response_text, str):
147+
return response_text
148+
if isinstance(response_text, (bytes, bytearray, memoryview)):
149+
try:
150+
return memoryview(response_text).tobytes().decode("utf-8")
151+
except (TypeError, ValueError, UnicodeDecodeError):
152+
return ""
153+
return _safe_to_string(response_text)
154+
155+
145156
def _stringify_error_value(value: Any, *, _depth: int = 0) -> str:
146157
if _depth > 10:
147158
return _safe_to_string(value)
@@ -191,7 +202,7 @@ def _stringify_error_value(value: Any, *, _depth: int = 0) -> str:
191202
def extract_error_message(response: httpx.Response, fallback_error: Exception) -> str:
192203
def _fallback_message() -> str:
193204
try:
194-
response_text = response.text
205+
response_text = _normalize_response_text_for_error_message(response.text)
195206
except Exception:
196207
response_text = ""
197208
if isinstance(response_text, str) and response_text.strip():

tests/test_transport_error_utils.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ def json(self):
173173
raise ValueError("invalid json")
174174

175175

176+
class _BytesFallbackResponse:
177+
def __init__(self, response_text: bytes) -> None:
178+
self._response_text = response_text
179+
180+
@property
181+
def text(self) -> bytes:
182+
return self._response_text
183+
184+
def json(self):
185+
raise ValueError("invalid json")
186+
187+
176188
class _BrokenGetErrorDict(dict):
177189
def get(self, key, default=None):
178190
_ = key
@@ -734,6 +746,24 @@ def test_extract_error_message_uses_response_text_for_blank_string_payload():
734746
assert message == "raw error body"
735747

736748

749+
def test_extract_error_message_uses_utf8_bytes_response_text_fallback():
750+
message = extract_error_message(
751+
_BytesFallbackResponse("raw bytes body".encode("utf-8")), # type: ignore[arg-type]
752+
RuntimeError("fallback detail"),
753+
)
754+
755+
assert message == "raw bytes body"
756+
757+
758+
def test_extract_error_message_uses_fallback_for_invalid_bytes_response_text():
759+
message = extract_error_message(
760+
_BytesFallbackResponse(b"\xff\xfe"), # type: ignore[arg-type]
761+
RuntimeError("fallback detail"),
762+
)
763+
764+
assert message == "fallback detail"
765+
766+
737767
def test_extract_error_message_uses_fallback_error_when_response_text_is_blank():
738768
message = extract_error_message(
739769
_DummyResponse(" ", text=" "),

0 commit comments

Comments
 (0)