-
Notifications
You must be signed in to change notification settings - Fork 60
/
requesthandlers.py
92 lines (71 loc) · 2.93 KB
/
requesthandlers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import logging
from tornado.web import RequestHandler
from jsonschema import ValidationError
from tornado_json.jsend import JSendMixin
from tornado_json.utils import APIError
class BaseHandler(RequestHandler):
"""
BaseHandler for all other RequestHandlers
"""
@property
def db_conn(self):
"""Returns database connection abstraction
If no database connection is available, raises an AttributeError
"""
db_conn = self.application.db_conn
if not db_conn:
raise AttributeError("No database connection was provided.")
return db_conn
class ViewHandler(BaseHandler):
"""Handler for views"""
def initialize(self):
"""
- Set Content-type for HTML
"""
self.set_header("Content-Type", "text/html")
class APIHandler(BaseHandler, JSendMixin):
"""
RequestHandler for API calls
- Sets header as application/json
- Provides custom write_error that writes error back as JSON
rather than as the standard HTML template
"""
def initialize(self):
"""
- Set Content-type for JSON
"""
self.set_header("Content-Type", "application/json")
def write_error(self, status_code, **kwargs):
"""Override of RequestHandler.write_error
Calls `error()` or `fail()` from JSendMixin depending on which
exception was raised with provided reason and status code.
:type status_code: int
:param status_code: HTTP status code
"""
self.clear()
# If exc_info is not in kwargs, something is very fubar
if not "exc_info" in list(kwargs.keys()):
logging.error("exc_info not provided")
self.set_status(500)
self.error(message="Internal Server Error", code=500)
self.finish()
self.set_status(status_code)
# Any APIError exceptions raised will result in a JSend fail written
# back with the log_message as data. Hence, log_message should NEVER
# expose internals. Since log_message is proprietary to HTTPError
# class exceptions, all exceptions without it will return their
# __str__ representation.
# All other exceptions result in a JSend error being written back,
# with log_message only written if debug mode is enabled
exception = kwargs["exc_info"][1]
if any(isinstance(exception, c) for c in [APIError, ValidationError]):
# ValidationError is always due to a malformed request
if isinstance(exception, ValidationError):
self.set_status(400)
self.fail(exception.log_message if
hasattr(exception, "log_message") else str(exception))
else:
self.error(message=self._reason,
data=exception.log_message if self.settings.get(
"debug") else None,
code=status_code)