Skip to content

Commit feecb9a

Browse files
authored
Merge pull request #19 from stax-labs/feat/handle-http-error
feat(api) handle http errors
2 parents 8dc5862 + c693b6e commit feecb9a

3 files changed

Lines changed: 53 additions & 12 deletions

File tree

staxapp/api.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ def handle_api_response(response):
2323
try:
2424
response.raise_for_status()
2525
except requests.exceptions.HTTPError as e:
26-
logging.error(f"{response.status_code}: {response.json()}")
27-
2826
raise ApiException(str(e), response)
2927

3028
@classmethod

staxapp/exceptions.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1+
import logging
2+
from json.decoder import JSONDecodeError
3+
4+
15
class ApiException(Exception):
26
def __init__(self, message, response, detail=""):
3-
prefix = f"Api Exception: {response.status_code} - "
4-
if detail:
5-
prefix = f"{prefix}{detail} "
6-
if response.json().get("Error"):
7-
print("Some error")
8-
self.message = f"{prefix}{response.json()['Error']}"
9-
else:
10-
print("No Error")
11-
self.message = f"{prefix}{message}"
7+
try:
8+
if response.json().get("Error"):
9+
logging.error(f"{response.status_code}: {response.json()}")
10+
self.message = f"Api Exception: {response.status_code} -{detail} {response.json()['Error']}"
11+
else:
12+
logging.error(f"{response.status_code}: {response.json()}")
13+
self.message = f"Api Exception:{detail} {message}"
14+
except JSONDecodeError:
15+
if response.content:
16+
logging.error(f"{response.status_code}: {response.content}")
17+
else:
18+
logging.error(f"{response.status_code}: {message}")
19+
self.message = f"Api Exception:{detail} {message}"
1220

1321
def __str__(self):
1422
return self.message

tests/test_api.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def testFailedPut(self):
161161
)
162162
payload = {"Unit": "Test"}
163163
with self.assertRaises(ApiException):
164-
response = self.Api.put("/test/put/400", payload)
164+
self.Api.put("/test/put/400", payload)
165165

166166
@responses.activate
167167
def testDelete(self):
@@ -194,6 +194,41 @@ def testFailedDelete(self):
194194
with self.assertRaises(ApiException):
195195
self.Api.delete("/test/delete/exception")
196196

197+
@responses.activate
198+
def testFailedApiException(self):
199+
"""
200+
Test all paths of ApiException
201+
"""
202+
# Test Exception with no error in response
203+
response_dict = {}
204+
responses.add(
205+
responses.GET,
206+
f"{Config.api_base_url()}/test/no/error",
207+
json=response_dict,
208+
status=500,
209+
)
210+
with self.assertRaises(ApiException):
211+
self.Api.get("/test/no/error")
212+
213+
# Test an exception which has no json in response
214+
responses.add(
215+
responses.GET,
216+
f"{Config.api_base_url()}/test/invalid/json",
217+
body='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>405 Method Not Allowed</title>\n<h1>Method Not Allowed</h1>\n<p>The method is not allowed for the requested URL.</p>\n',
218+
status=405,
219+
)
220+
with self.assertRaises(ApiException):
221+
self.Api.get("/test/invalid/json")
222+
223+
# Test an exception with no content
224+
responses.add(
225+
responses.GET,
226+
f"{Config.api_base_url()}/test/no/content",
227+
status=500,
228+
)
229+
with self.assertRaises(ApiException):
230+
self.Api.get("/test/no/content")
231+
197232

198233
if __name__ == "__main__":
199234
unittest.main()

0 commit comments

Comments
 (0)