Skip to content

Commit 993e0cc

Browse files
authored
Fixes #25: better error handling in api, more verbose error responses (#26)
* chore: better error handling in api, more verbose error responses * tests: improve assertions in TestBasic
1 parent 0a16b75 commit 993e0cc

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

Diff for: flask_shell2http/api.py

+33-9
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# lib imports
2121
from .classes import RunnerParser
2222
from .helpers import get_logger
23-
23+
from .exceptions import JobNotFoundException, JobStillRunningException
2424

2525
logger = get_logger()
2626
runner_parser = RunnerParser()
@@ -34,8 +34,9 @@ class Shell2HttpAPI(MethodView):
3434
"""
3535

3636
def get(self):
37+
key: str = ""
3738
try:
38-
key: str = request.args.get("key")
39+
key = request.args.get("key")
3940
logger.info(
4041
f"Job: '{key}' --> Report requested. "
4142
f"Requester: '{request.remote_addr}'."
@@ -46,29 +47,44 @@ def get(self):
4647
# get the future object
4748
future: Future = self.executor.futures._futures.get(key)
4849
if not future:
49-
raise Exception(f"No report exists for key: '{key}'.")
50+
raise JobNotFoundException(f"No report exists for key: '{key}'.")
5051

5152
# check if job has been finished
5253
if not future.done():
53-
logger.debug(f"Job: '{key}' --> still running.")
54-
return make_response(jsonify(status="running", key=key), 200)
54+
raise JobStillRunningException()
5555

5656
# pop future object since it has been finished
5757
self.executor.futures.pop(key)
5858

5959
# if yes, get result from store
6060
report: Dict = future.result()
6161
if not report:
62-
raise Exception(f"Job: '{key}' --> No report exists.")
62+
raise JobNotFoundException(f"Job: '{key}' --> No report exists.")
6363

6464
logger.debug(f"Job: '{key}' --> Requested report: {report}")
6565
return jsonify(report)
6666

67-
except Exception as e:
67+
except JobNotFoundException as e:
6868
logger.error(e)
6969
return make_response(jsonify(error=str(e)), HTTPStatus.NOT_FOUND)
7070

71+
except JobStillRunningException:
72+
logger.debug(f"Job: '{key}' --> still running.")
73+
return make_response(
74+
jsonify(
75+
status="running",
76+
key=key,
77+
result_url=self.__build_result_url(key),
78+
),
79+
HTTPStatus.OK,
80+
)
81+
82+
except Exception as e:
83+
logger.error(e)
84+
return make_response(jsonify(error=str(e)), HTTPStatus.BAD_REQUEST)
85+
7186
def post(self):
87+
key: str = ""
7288
try:
7389
logger.info(
7490
f"Received request for endpoint: '{request.url_rule}'. "
@@ -96,15 +112,23 @@ def post(self):
96112
)
97113

98114
logger.info(f"Job: '{key}' --> added to queue for command: {cmd}")
99-
result_url = f"{request.base_url}?key={key}"
115+
result_url = self.__build_result_url(key)
100116
return make_response(
101117
jsonify(status="running", key=key, result_url=result_url),
102118
HTTPStatus.ACCEPTED,
103119
)
104120

105121
except Exception as e:
106122
logger.error(e)
107-
return make_response(jsonify(error=str(e)), HTTPStatus.BAD_REQUEST)
123+
response_dict = {"error": str(e)}
124+
if key:
125+
response_dict["key"] = key
126+
response_dict["result_url"] = self.__build_result_url(key)
127+
return make_response(jsonify(response_dict), HTTPStatus.BAD_REQUEST)
128+
129+
@classmethod
130+
def __build_result_url(cls, key: str) -> str:
131+
return f"{request.base_url}?key={key}"
108132

109133
def __init__(
110134
self,

Diff for: flask_shell2http/exceptions.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class JobNotFoundException(Exception):
2+
"""
3+
Raised when no job exists for requested key.
4+
"""
5+
6+
7+
class JobStillRunningException(Exception):
8+
"""
9+
Raised when job is still running.
10+
"""

Diff for: tests/test_basic.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def test_duplicate_request_raises_error(self):
6161
)
6262
r2_json = r2.get_json()
6363
self.assertIn("error", r2_json)
64+
self.assertIn("key", r2_json)
65+
self.assertIn("result_url", r2_json)
6466

6567
def test_duplicate_request_after_report_fetch(self):
6668
data = {"args": ["test_duplicate_request_after_report_fetch"]}
@@ -72,7 +74,8 @@ def test_duplicate_request_after_report_fetch(self):
7274
# now make 2nd request
7375
r2 = self.client.post(self.uri, json=data)
7476
r2_json = r2.get_json()
75-
self.assertEqual(r2_json["key"], r1_json["key"])
77+
# should have same response
78+
self.assertDictEqual(r2_json, r1_json)
7679

7780
def test_force_unique_key(self):
7881
data = {"args": ["test_force_unique_key"]}

0 commit comments

Comments
 (0)