Skip to content

Commit 8b2f171

Browse files
Update raise errors. (#282)
* Update raise errors. * Refactor error handling.
1 parent e12148a commit 8b2f171

File tree

2 files changed

+63
-24
lines changed

2 files changed

+63
-24
lines changed

src/handlers/api.py

+24-24
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
@@ -67,7 +68,7 @@ def get(self):
6768
# raising HTTPError will cause headers to be emptied
6869
self.finish()
6970
else:
70-
raise HTTPError(403)
71+
raise HTTPError(status_code=403)
7172

7273

7374
class LoginHandler(AuthHandler):
@@ -112,7 +113,7 @@ class ValidateHandler(BaseHandler):
112113

113114
async def get(self):
114115
if self.request.body:
115-
raise HTTPError(400, reason="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)
@@ -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(400, reason=str(err))
143+
raise SmartAPIHTTPError(400, reason=str(err))
144144
else:
145145
self.finish({"success": True, "details": f"valid SmartAPI ({smartapi.version}) metadata."})
146146

@@ -164,19 +164,19 @@ async def post(self):
164164
"""
165165

166166
if SmartAPI.find(self.args.url, "url"):
167-
raise HTTPError(409)
167+
raise HTTPError(status_code=409)
168168

169169
try:
170170
file = await download_async(self.args.url)
171171
except DownloadError as err:
172-
raise HTTPError(400, reason=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(400, reason=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(400, reason=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)
@@ -251,21 +251,21 @@ async def put(self, _id):
251251
try:
252252
smartapi = SmartAPI.get(_id)
253253
except NotFoundError:
254-
raise HTTPError(404)
254+
raise HTTPError(status_code=404)
255255

256256
if smartapi.username != self.current_user["login"]:
257-
raise HTTPError(403)
257+
raise HTTPError(status_code=403)
258258

259259
if self.args.slug is not None:
260260
if self.args.slug in {"api"}: # reserved
261-
raise HTTPError(400, reason="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(400, reason=str(err)) from err
268+
raise HTTPError(status_code=400, reason=str(err)) from err
269269

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

@@ -291,15 +291,15 @@ def delete(self, _id):
291291
try:
292292
smartapi = SmartAPI.get(_id)
293293
except NotFoundError:
294-
raise HTTPError(404)
294+
raise HTTPError(status_code=404)
295295

296296
if smartapi.username != self.current_user["login"]:
297-
raise HTTPError(403)
297+
raise HTTPError(status_code=403)
298298

299299
try:
300300
_id = smartapi.delete()
301301
except ControllerError as err:
302-
raise HTTPError(400, reason=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,41 +345,41 @@ class UptimeHandler(BaseHandler):
345345
@github_authenticated
346346
def get(self):
347347
if self.request.body:
348-
raise HTTPError(400, reason="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:
352352
smartapi = SmartAPI.get(self.args.id)
353353
if smartapi.username != self.current_user["login"]:
354-
raise HTTPError(403)
354+
raise HTTPError(status_code=403)
355355
status = smartapi.check()
356356
smartapi.save()
357357
except NotFoundError:
358-
raise HTTPError(404)
358+
raise HTTPError(status_code=404)
359359
except (ControllerError, AssertionError) as err:
360-
raise HTTPError(400, reason=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(400, reason="Missing required parameter: id")
364+
raise HTTPError(status_code=400, reason="Missing required parameter: id")
365365

366366
@github_authenticated
367367
def post(self):
368368
if self.args.id:
369369
try:
370370
smartapi = SmartAPI.get(self.args.id)
371371
if smartapi.username != self.current_user["login"]:
372-
raise HTTPError(403)
372+
raise HTTPError(status_code=403)
373373
status = smartapi.check()
374374
smartapi.save()
375375
except NotFoundError:
376-
raise HTTPError(404)
376+
raise HTTPError(status_code=404)
377377
except (ControllerError, AssertionError) as err:
378-
raise HTTPError(400, reason=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(400, reason="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

+39
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)