Skip to content

Commit 71cb656

Browse files
fix: Handle non-json error responses (#263)
* Handle non-json error responses * Catch specific errors * Fix lint too many return statements * Test non-standard response * Move is_api_error_response out of SeamHttpClient class
1 parent afd785a commit 71cb656

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

seam/client.py

+32
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ def _handle_error_response(self, response: requests.Response):
6161
if status_code == 401:
6262
raise SeamHttpUnauthorizedError(request_id)
6363

64+
if not is_api_error_response(response):
65+
response.raise_for_status()
66+
6467
error = response.json().get("error", {})
6568
error_type = error.get("type", "unknown_error")
6669
error_message = error.get("message", "Unknown error")
@@ -76,3 +79,32 @@ def _handle_error_response(self, response: requests.Response):
7679
raise SeamHttpInvalidInputError(error_details, status_code, request_id)
7780

7881
raise SeamHttpApiError(error_details, status_code, request_id)
82+
83+
84+
def is_api_error_response(response: requests.Response) -> bool:
85+
try:
86+
content_type = response.headers.get("content-type", "")
87+
88+
if not isinstance(content_type, str) or not content_type.startswith(
89+
"application/json"
90+
):
91+
return False
92+
93+
data = response.json()
94+
except (ValueError, requests.exceptions.JSONDecodeError):
95+
return False
96+
97+
if not isinstance(data, dict):
98+
return False
99+
100+
error = data.get("error")
101+
102+
if not isinstance(error, dict):
103+
return False
104+
105+
if not isinstance(error.get("type"), str) or not isinstance(
106+
error.get("message"), str
107+
):
108+
return False
109+
110+
return True

test/http_error_test.py

+16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
import niquests
23
from seam import Seam
34
from seam.exceptions import (
45
SeamHttpApiError,
@@ -44,3 +45,18 @@ def test_seam_http_throws_invalid_input_error(server):
4445
assert err.status_code == 400
4546
assert err.code == "invalid_input"
4647
assert err.request_id.startswith("request")
48+
49+
50+
def test_seam_http_throws_http_error_on_non_standard_response(server):
51+
endpoint, seed = server
52+
seam = Seam.from_api_key(seed["seam_apikey1_token"], endpoint=endpoint)
53+
54+
seam.client.post(
55+
"/_fake/simulate_workspace_outage",
56+
json={"workspace_id": seed["seed_workspace_1"], "routes": ["/devices/list"]},
57+
)
58+
59+
with pytest.raises(niquests.HTTPError) as exc_info:
60+
seam.devices.list()
61+
62+
assert exc_info.value.response.status_code == 503

0 commit comments

Comments
 (0)