Skip to content

Commit 898a7ff

Browse files
committed
Ensure error handling logic is displaying the issue on the UI
1 parent 83960b0 commit 898a7ff

File tree

4 files changed

+41
-41
lines changed

4 files changed

+41
-41
lines changed

api/src/routes/errors.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,44 +67,40 @@ def handler_validationerror(e):
6767
return make_response(jsonify({"message": e.messages}), HTTPStatus.BAD_REQUEST)
6868

6969

70-
# 400
71-
class BadRequest(Exception):
70+
class ExceptionWithMessage(Exception):
7271
def __init__(self, message: str = None):
7372
self.message = message
7473

74+
@staticmethod
75+
def handler(e, status: HTTPStatus):
76+
if isinstance(e, ExceptionWithMessage) and e.message is not None:
77+
return make_response(jsonify({"error": e.message}), status)
78+
return Response(status=status)
79+
80+
81+
# 400
82+
class BadRequest(ExceptionWithMessage):
7583
@staticmethod
7684
def handler(e):
77-
if isinstance(e, BadRequest) and e.message is not None:
78-
return make_response(jsonify({"error": e.message}), HTTPStatus.BAD_REQUEST)
79-
return Response(status=HTTPStatus.BAD_REQUEST)
85+
return super().handler(e, HTTPStatus.BAD_REQUEST)
8086

8187

8288
# 401
83-
class Unauthorized(Exception):
84-
def __init__(self, message: str = None):
85-
self.message = message
86-
89+
class Unauthorized(ExceptionWithMessage):
8790
@staticmethod
8891
def handler(e):
89-
if isinstance(e, Unauthorized) and e.message is not None:
90-
return make_response(jsonify({"error": e.message}), HTTPStatus.UNAUTHORIZED)
91-
return Response(status=HTTPStatus.UNAUTHORIZED)
92+
return super().handler(e, HTTPStatus.UNAUTHORIZED)
9293

9394

9495
# 404
95-
class NotFound(Exception):
96-
def __init__(self, message: str = None):
97-
self.message = message
98-
96+
class NotFound(ExceptionWithMessage):
9997
@staticmethod
10098
def handler(e):
101-
if isinstance(e, NotFound) and e.message is not None:
102-
return make_response(jsonify({"error": e.message}), HTTPStatus.NOT_FOUND)
103-
return Response(status=HTTPStatus.NOT_FOUND)
99+
return super().handler(e, HTTPStatus.NOT_FOUND)
104100

105101

106102
# 500
107-
class InternalError(Exception):
103+
class InternalError(ExceptionWithMessage):
108104
@staticmethod
109105
def handler(e):
110-
return Response(status=HTTPStatus.INTERNAL_SERVER_ERROR)
106+
return super().handler(e, HTTPStatus.INTERNAL_SERVER_ERROR)

api/src/routes/requests.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,15 @@ def post(self, *args, **kwargs):
129129
success, status, resp = query_api("POST", "/schedules/", payload=payload)
130130
if not success:
131131
logger.error(f"Unable to create schedule via HTTP {status}: {resp}")
132-
raise InternalError(f"Unable to create schedule via HTTP {status}: {resp}")
132+
message = f"Unable to create schedule via HTTP {status}: {resp}"
133+
if status == http.HTTPStatus.BAD_REQUEST:
134+
# if Zimfarm replied this is a bad request, then this is most probably
135+
# a bad request due to user input so we can track it like a bad request
136+
raise InternalError()
137+
# raise BadRequest(message)
138+
else:
139+
# otherwise, this is most probably an internal problem in our systems
140+
raise InternalError(message)
133141

134142
# request a task for that newly created schedule
135143
success, status, resp = query_api(
@@ -138,23 +146,22 @@ def post(self, *args, **kwargs):
138146
payload={"schedule_names": [schedule_name], "worker": TASK_WORKER},
139147
)
140148
if not success:
141-
logger.error(f"Unable to request {schedule_name} via HTTP {status}")
142-
logger.debug(resp)
143-
raise InternalError(f"Unable to request schedule via HTTP {status}: {resp}")
149+
logger.error(f"Unable to request {schedule_name} via HTTP {status}: {resp}")
150+
raise InternalError(
151+
f"Unable to request schedule via HTTP {status}): {resp}"
152+
)
144153

145154
try:
146155
task_id = resp.get("requested").pop()
147156
if not task_id:
148-
raise ValueError("task_id is False")
157+
raise InternalError("task_id is False")
149158
except Exception as exc:
150159
raise InternalError(f"Couldn't retrieve requested task id: {exc}")
151160

152161
# remove newly created schedule (not needed anymore)
153162
success, status, resp = query_api("DELETE", f"/schedules/{schedule_name}")
154163
if not success:
155-
logger.error(f"Unable to remove schedule {schedule_name} via HTTP {status}")
156-
logger.debug(resp)
157-
164+
logger.error(f"Unable to remove schedule {schedule_name} via HTTP {status}: {resp}")
158165
return make_response(jsonify({"id": str(task_id)}), http.HTTPStatus.CREATED)
159166

160167

ui/src/components/NewRequest.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@
233233
throw "Didn't receive task_id";
234234
})
235235
.catch(function (error) {
236-
parent.alertError("Unable to create schedule:\n" + Constants.standardHTTPError(error.response));
236+
parent.alertError("Unable to request ZIM creation:<br />" + Constants.standardHTTPError(error.response));
237237
})
238238
.then(function () {
239239
parent.toggleLoader(false);

ui/src/constants.js

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,16 @@ export default {
9898
599: "Network Connect Timeout Error",
9999
};
100100

101-
if (response === undefined) { // no response
102-
//usually due to browser blocking failed OPTION preflight request
103-
return "Cross-Origin Request Blocked: preflight request failed."
101+
if (response === undefined) {
102+
// no response is usually due to browser blocking due to CORS issue
103+
return "Unknown response; probably CORS issue."
104104
}
105-
let status_text = response.statusText ? response.statusText : statuses[response.status];
106-
if (response.status == 400) {
107-
if (response.data && response.data.error)
108-
status_text += "<br />" + JSON.stringify(response.data.error);
109-
if (response.data && response.data.error_description)
110-
status_text += "<br />" + JSON.stringify(response.data.error_description);
111-
if (response.data && response.data.message)
112-
status_text += "<br />" + JSON.stringify(response.data.message);
105+
// If error is provided, display it (do not display error code since this is too technical)
106+
if (response.data && response.data.error) {
107+
return response.data.error;
113108
}
109+
// Last resort, display only available information
110+
let status_text = response.statusText ? response.statusText : statuses[response.status];
114111
return response.status + ": " + status_text + ".";
115112
},
116113
};

0 commit comments

Comments
 (0)