]> git.ipfire.org Git - pbs.git/commitdiff
web: Send better errors for failed upload requests
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 19 Oct 2023 20:40:37 +0000 (20:40 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 19 Oct 2023 20:40:37 +0000 (20:40 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/web/base.py
src/web/uploads.py

index 815beda99a65ece2eff815895df433c57a806351..6ec2fa9b9037aa02bef66e96849a33639a27c83f 100644 (file)
@@ -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):
index 9172473b2af4e6881d2cbe151be0f1c370e4c4f6..9414b06c1e8ebe6164576dc1576f690a80a84a9b 100644 (file)
@@ -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):