From c27e7f37888e8700aa043129462b4bd209fbf1c4 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Thu, 19 Oct 2023 20:40:37 +0000 Subject: [PATCH] web: Send better errors for failed upload requests Signed-off-by: Michael Tremer --- src/web/base.py | 35 +++++++++++++++++++++++++++++++---- src/web/uploads.py | 10 ++++------ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/web/base.py b/src/web/base.py index 815beda9..6ec2fa9b 100644 --- a/src/web/base.py +++ b/src/web/base.py @@ -310,6 +310,20 @@ class BaseHandler(tornado.web.RequestHandler): # XXX TODO BackendMixin = BaseHandler +class APIError(Exception): + """ + Raised if there has been an error in the API + """ + def __init__(self, code, message): + super().__init__() + + self.code = code + self.message = message + + def __str__(self): + return self.message + + class APIMixin(KerberosAuthMixin, BackendMixin): # Generally do not permit users to authenticate against the API allow_users = False @@ -367,11 +381,24 @@ class APIMixin(KerberosAuthMixin, BackendMixin): "mem_level" : 9, } - def write_error(self, code, **kwargs): - # Send a JSON-encoded error message + def write_error(self, code, exc_info): + """ + Sends a JSON-encoded error message + """ + type, error, traceback = exc_info + + # We only handle API errors here + if not isinstance(error, APIError): + return super().write_error(code, exc_info) + + # We send errors as 200 + self.set_status(200, reason=error.message) + self.finish({ - "error" : True, - # XXX add error string + "error" : { + "code" : error.code, + "message" : error.message, + }, }) def _decode_json_message(self, message): diff --git a/src/web/uploads.py b/src/web/uploads.py index 9172473b..9414b06c 100644 --- a/src/web/uploads.py +++ b/src/web/uploads.py @@ -84,15 +84,13 @@ class APIv1IndexHandler(base.APIMixin, tornado.web.RequestHandler): ) except uploads.UnsupportedDigestException as e: - raise tornado.web.HTTPError(400, - "Unsupported digest %s" % digest_algo) from e + raise base.APIError(400, "Unsupported digest %s" % digest_algo) from e except users.QuotaExceededError as e: - raise tornado.web.HTTPError(400, - "Quota exceeded for %s" % self.current_user) from e + raise base.APIError(400, "Quota exceeded for %s" % self.current_user) from e except ValueError as e: - raise tornado.web.HTTPError(400, "%s" % e) from e + raise base.APIError(400, "%s" % e) from e # Send the ID of the upload back to the client self.finish({ @@ -138,7 +136,7 @@ class APIv1DetailHandler(base.APIMixin, tornado.web.RequestHandler): await upload.copyfrom(self.buffer) except ValueError as e: - raise tornado.web.HTTPError(400, "%s" % e) from e + raise base.APIError(400, "%s" % e) from e @base.negotiate async def delete(self, uuid): -- 2.47.2