mirror of
https://github.com/sprockets/sprockets.http.git
synced 2024-11-14 19:29:28 +00:00
ErrorWriter: Add support for format_traceback.
This commit is contained in:
parent
cdb655be1e
commit
a7c8d95847
2 changed files with 39 additions and 9 deletions
|
@ -8,6 +8,7 @@ HTTP related utility mixins.
|
|||
"""
|
||||
import logging
|
||||
import json
|
||||
import traceback
|
||||
|
||||
from tornado import httputil
|
||||
|
||||
|
@ -79,7 +80,7 @@ class ErrorWriter(object):
|
|||
|
||||
Mix this class in to your inheritance chain to include error
|
||||
bodies as a standard JSON document. The error document has
|
||||
two simple properties:
|
||||
three simple properties:
|
||||
|
||||
**type**
|
||||
This is the type of exception that occurred or ``null``.
|
||||
|
@ -98,18 +99,27 @@ class ErrorWriter(object):
|
|||
neither an exception nor a custom reason, the string ``Unknown``
|
||||
will be used.
|
||||
|
||||
**traceback**
|
||||
If the application is configured to serve tracebacks and the
|
||||
error was caused by an exception (based on ``exc_info`` kwarg),
|
||||
then this is the formatted traceback as an array of strings
|
||||
returned from :func:`traceback.format_exception`. Otherwise,
|
||||
this property is set to ``null``.
|
||||
|
||||
"""
|
||||
|
||||
def write_error(self, status_code, **kwargs):
|
||||
error_body = {'type': None}
|
||||
error_body = {'type': None, 'traceback': None}
|
||||
exc_type, exc_value, _ = kwargs.get('exc_info', (None, None, None))
|
||||
if exc_type and exc_value:
|
||||
error_body['type'] = exc_type.__name__
|
||||
error_body.setdefault('message', str(exc_value))
|
||||
if self.settings.get('serve_traceback', False):
|
||||
error_body['traceback'] = traceback.format_exception(
|
||||
*kwargs['exc_info'])
|
||||
else:
|
||||
error_body.setdefault('message',
|
||||
kwargs.get('reason',
|
||||
_get_http_reason(status_code)))
|
||||
reason = kwargs.get('reason', _get_http_reason(status_code))
|
||||
error_body.setdefault('message', reason)
|
||||
|
||||
self.set_header('Content-Type', 'application/json')
|
||||
self.write(json.dumps(error_body).encode('utf-8'))
|
||||
|
|
28
tests.py
28
tests.py
|
@ -86,11 +86,22 @@ class ErrorLoggerTests(testing.AsyncHTTPTestCase):
|
|||
|
||||
class ErrorWriterTests(testing.AsyncHTTPTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self._application = None
|
||||
super(ErrorWriterTests, self).setUp()
|
||||
|
||||
@property
|
||||
def application(self):
|
||||
if self._application is None:
|
||||
self._application = web.Application([
|
||||
web.url(r'/status/(?P<status_code>\d+)',
|
||||
examples.StatusHandler),
|
||||
web.url(r'/fail/(?P<status_code>\d+)', RaisingHandler),
|
||||
])
|
||||
return self._application
|
||||
|
||||
def get_app(self):
|
||||
return web.Application([
|
||||
web.url(r'/status/(?P<status_code>\d+)', examples.StatusHandler),
|
||||
web.url(r'/fail/(?P<status_code>\d+)', RaisingHandler),
|
||||
])
|
||||
return self.application
|
||||
|
||||
def _decode_response(self, response):
|
||||
content_type = response.headers['Content-Type']
|
||||
|
@ -141,3 +152,12 @@ class ErrorWriterTests(testing.AsyncHTTPTestCase):
|
|||
|
||||
body = self._decode_response(response)
|
||||
self.assertEqual(body['message'], 'Unknown')
|
||||
|
||||
def test_that_error_json_honors_serve_traceback(self):
|
||||
self.application.settings['serve_traceback'] = True
|
||||
|
||||
response = self.fetch('/fail/400')
|
||||
self.assertEqual(response.code, 400)
|
||||
|
||||
body = self._decode_response(response)
|
||||
self.assertGreater(len(body['traceback']), 0)
|
||||
|
|
Loading…
Reference in a new issue