Skip to content

Commit 6c3d036

Browse files
Refactor error handling.
1 parent 2a6108a commit 6c3d036

2 files changed

Lines changed: 54 additions & 15 deletions

File tree

src/handlers/api.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from controller.exceptions import ControllerError, NotFoundError
1818
from pipeline import MetaKGQueryPipeline
1919
from utils.downloader import DownloadError, download_async
20+
from utils.http_error import SmartAPIHTTPError
2021
from utils.metakg.export import edges2graphml
2122
from utils.metakg.path_finder import MetaKGPathFinder
2223
from utils.metakg.cytoscape_formatter import CytoscapeDataFormatter
@@ -112,7 +113,7 @@ class ValidateHandler(BaseHandler):
112113

113114
async def get(self):
114115
if self.request.body:
115-
raise HTTPError(status_code=400, log_message="GET takes no request body.")
116+
raise HTTPError(status_code=400, reason="GET takes no request body.")
116117

117118
raw = await self.download(self.args.url)
118119
self.validate(raw)
@@ -129,7 +130,7 @@ async def download(self, url):
129130
try:
130131
file = await download_async(url)
131132
except DownloadError as err:
132-
raise HTTPError(status_code=400, log_message=str(err))
133+
raise HTTPError(400, reason=str(err))
133134
else: # other file info irrelevant for validation
134135
return file.raw
135136

@@ -138,9 +139,8 @@ def validate(self, raw):
138139
smartapi = SmartAPI(SmartAPI.VALIDATION_ONLY)
139140
smartapi.raw = raw
140141
smartapi.validate()
141-
142142
except (ControllerError, AssertionError) as err:
143-
raise HTTPError(status_code=400, log_message=str(err))
143+
raise SmartAPIHTTPError(400, reason=str(err))
144144
else:
145145
self.finish({"success": True, "details": f"valid SmartAPI ({smartapi.version}) metadata."})
146146

@@ -169,14 +169,14 @@ async def post(self):
169169
try:
170170
file = await download_async(self.args.url)
171171
except DownloadError as err:
172-
raise HTTPError(status_code=400, log_message=str(err)) from err
172+
raise HTTPError(status_code=400, reason=str(err)) from err
173173

174174
try:
175175
smartapi = SmartAPI(self.args.url)
176176
smartapi.raw = file.raw
177177
smartapi.validate()
178178
except (ControllerError, AssertionError) as err:
179-
raise HTTPError(status_code=400, log_message=str(err)) from err
179+
raise HTTPError(status_code=400, reason=str(err)) from err
180180

181181
if self.args.dryrun:
182182
raise Finish({"success": True, "details": f"[Dryrun] Valid {smartapi.version} Metadata"})
@@ -186,7 +186,7 @@ async def post(self):
186186
smartapi.refresh(file) # populate webdoc meta
187187
_id = smartapi.save()
188188
except ControllerError as err:
189-
raise HTTPError(status_code=400, log_message=str(err)) from err
189+
raise HTTPError(status_code=400, reason=str(err)) from err
190190
else:
191191
self.finish({"success": True, "_id": _id})
192192
await self._notify(smartapi)
@@ -258,14 +258,14 @@ async def put(self, _id):
258258

259259
if self.args.slug is not None:
260260
if self.args.slug in {"api"}: # reserved
261-
raise HTTPError(status_code=400, log_message="slug is reserved")
261+
raise HTTPError(status_code=400, reason="slug is reserved")
262262

263263
try: # update slug
264264
smartapi.slug = self.args.slug or None
265265
smartapi.save()
266266

267267
except (ControllerError, ValueError) as err:
268-
raise HTTPError(status_code=400, log_message=str(err)) from err
268+
raise HTTPError(status_code=400, reason=str(err)) from err
269269

270270
self.finish({"success": True})
271271

@@ -299,7 +299,7 @@ def delete(self, _id):
299299
try:
300300
_id = smartapi.delete()
301301
except ControllerError as err:
302-
raise HTTPError(status_code=400, log_message=str(err)) from err
302+
raise HTTPError(status_code=400, reason=str(err)) from err
303303

304304
self.finish({"success": True, "_id": _id})
305305

@@ -345,7 +345,7 @@ class UptimeHandler(BaseHandler):
345345
@github_authenticated
346346
def get(self):
347347
if self.request.body:
348-
raise HTTPError(status_code=400, log_message="GET takes no request body.")
348+
raise HTTPError(status_code=400, reason="GET takes no request body.")
349349

350350
if self.args.id:
351351
try:
@@ -357,11 +357,11 @@ def get(self):
357357
except NotFoundError:
358358
raise HTTPError(status_code=404)
359359
except (ControllerError, AssertionError) as err:
360-
raise HTTPError(status_code=400, log_message=str(err))
360+
raise HTTPError(status_code=400, reason=str(err))
361361
else:
362362
self.finish({"success": True, "details": status})
363363
else:
364-
raise HTTPError(status_code=400, log_message="Missing required parameter: id")
364+
raise HTTPError(status_code=400, reason="Missing required parameter: id")
365365

366366
@github_authenticated
367367
def post(self):
@@ -375,11 +375,11 @@ def post(self):
375375
except NotFoundError:
376376
raise HTTPError(status_code=404)
377377
except (ControllerError, AssertionError) as err:
378-
raise HTTPError(status_code=400, log_message=str(err))
378+
raise HTTPError(status_code=400, reason=str(err))
379379
else:
380380
self.finish({"success": True, "details": status})
381381
else:
382-
raise HTTPError(status_code=400, log_message="Missing required form field: id")
382+
raise HTTPError(status_code=400, reason="Missing required form field: id")
383383

384384

385385
class MetaKGQueryHandler(QueryHandler):

src/utils/http_error.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from typing import Optional, Any
2+
from tornado.web import HTTPError
3+
import re
4+
5+
6+
class SmartAPIHTTPError(HTTPError):
7+
"""An extended HTTPError class with additional details and message sanitization.
8+
9+
Adds the following enhancements:
10+
- A `details` parameter for including extra context about the error.
11+
- A `clean_error_message` method for sanitizing log messages and details.
12+
13+
:arg str details: Additional information about the error.
14+
"""
15+
16+
def __init__(
17+
self,
18+
status_code: int = 500,
19+
log_message: Optional[str] = None,
20+
*args: Any,
21+
**kwargs: Any,
22+
) -> None:
23+
super().__init__(status_code, log_message, *args, **kwargs)
24+
if self.reason:
25+
self.reason = self.clean_error_message(self.reason)
26+
if self.log_message:
27+
self.log_message = self.clean_error_message(self.log_message)
28+
29+
@staticmethod
30+
def clean_error_message(message: str) -> str:
31+
"""
32+
Sanitizes an error message by replacing newlines, tabs, and reducing multiple spaces.
33+
34+
:param message: The error message to sanitize.
35+
:return: A cleaned and sanitized version of the message.
36+
"""
37+
message = message.replace("\n", " ") # Replace actual newlines with spaces
38+
message = re.sub(r'\s+', ' ', message) # Normalize spaces
39+
return message.strip()

0 commit comments

Comments
 (0)