mirror of
https://github.com/sprockets/sprockets.mixins.json_error.git
synced 2024-11-22 03:00:24 +00:00
Add JsonErrorMixin:
This commit adds the JsonErrorMixin for formatting error message from a given RequestHandler as JSON.
This commit is contained in:
parent
8a6b82c83c
commit
ca9e0b535b
4 changed files with 130 additions and 11 deletions
24
README.rst
24
README.rst
|
@ -24,12 +24,30 @@ Requirements
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
This examples demonstrates how to use ``sprockets.mixins.json_error`` by ...
|
This examples demonstrates how to use ``sprockets.mixins.json_error`` to format
|
||||||
|
errors as JSON.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
from sprockets import mixins.json_error
|
from sprockets import mixins.json_error
|
||||||
|
from tornado import web
|
||||||
|
|
||||||
|
class MyRequestHandler(statsd.RequestMetricsMixin,
|
||||||
|
web.RequestHandler):
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
raise web.HTTPError(404, log_message='My reason')
|
||||||
|
|
||||||
|
|
||||||
|
The response from the handler will automatically be formatted as:
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"message": "My reason",
|
||||||
|
"type": "Not Found"
|
||||||
|
}
|
||||||
|
|
||||||
# Example here
|
|
||||||
|
|
||||||
Version History
|
Version History
|
||||||
---------------
|
---------------
|
||||||
|
@ -48,4 +66,4 @@ Available at https://sprocketsmixinsjson_error.readthedocs.org/en/latest/history
|
||||||
:target: https://pypi.python.org/pypi/sprockets.mixins.json_error
|
:target: https://pypi.python.org/pypi/sprockets.mixins.json_error
|
||||||
|
|
||||||
.. |License| image:: https://pypip.in/license/sprockets.mixins.json_error/badge.svg?
|
.. |License| image:: https://pypip.in/license/sprockets.mixins.json_error/badge.svg?
|
||||||
:target: https://sprocketsmixinsjson_error.readthedocs.org
|
:target: https://sprocketsmixinsjson_error.readthedocs.org
|
||||||
|
|
|
@ -4,5 +4,42 @@ mixins.json_error
|
||||||
Handler mixin for writing JSON errors
|
Handler mixin for writing JSON errors
|
||||||
|
|
||||||
"""
|
"""
|
||||||
version_info = (0, 0, 0)
|
version_info = (1, 0, 0)
|
||||||
__version__ = '.'.join(str(v) for v in version_info)
|
__version__ = '.'.join(str(v) for v in version_info)
|
||||||
|
|
||||||
|
|
||||||
|
class JsonErrorMixin(object):
|
||||||
|
|
||||||
|
def write_error(self, status_code, **kwargs):
|
||||||
|
"""Suppress the automatic rendering of HTML code upon an error.
|
||||||
|
|
||||||
|
:param int status_code:
|
||||||
|
The HTTP status code the :class:`HTTPError` raised.
|
||||||
|
|
||||||
|
:param dict kwargs:
|
||||||
|
Automatically filled with exception information including
|
||||||
|
the error that was raised, the class of error raised, and an
|
||||||
|
object.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if kwargs.get('error'):
|
||||||
|
raised_error = kwargs.get('error')
|
||||||
|
else:
|
||||||
|
_, raised_error, _ = kwargs['exc_info']
|
||||||
|
|
||||||
|
error_message = getattr(
|
||||||
|
raised_error, 'log_message', 'Unexpected Error')
|
||||||
|
error_type = getattr(raised_error, 'error_type', self._reason)
|
||||||
|
|
||||||
|
self.error = {
|
||||||
|
'message': error_message,
|
||||||
|
'type': error_type,
|
||||||
|
}
|
||||||
|
if hasattr(raised_error, 'documentation_url'):
|
||||||
|
self.error['documentation_url'] = raised_error.documentation_url
|
||||||
|
|
||||||
|
error_status_code = getattr(raised_error, 'status_code', status_code)
|
||||||
|
self.set_status(error_status_code)
|
||||||
|
|
||||||
|
self.set_header('Content-Type', 'application/json; charset=UTF-8')
|
||||||
|
self.finish(self.error)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
coverage>=3.7,<4
|
coverage>=3.7,<4
|
||||||
coveralls>=0.4,<1
|
coveralls>=0.4,<1
|
||||||
nose>=1.3,<2
|
nose>=1.3,<2
|
||||||
|
tornado>=4.0,<5
|
||||||
|
|
77
tests.py
77
tests.py
|
@ -2,12 +2,75 @@
|
||||||
Tests for the sprockets.mixins.json_error package
|
Tests for the sprockets.mixins.json_error package
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import mock
|
import json
|
||||||
try:
|
|
||||||
import unittest2 as unittest
|
from sprockets.mixins import json_error
|
||||||
except ImportError:
|
from tornado import testing, web
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class MyTest(unittest.TestCase):
|
class HTTPErrorRequestHandler(
|
||||||
pass
|
json_error.JsonErrorMixin, web.RequestHandler):
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
raise web.HTTPError(400, 'Error Reason')
|
||||||
|
|
||||||
|
|
||||||
|
class CustomExceptionRequestHandler(
|
||||||
|
json_error.JsonErrorMixin, web.RequestHandler):
|
||||||
|
|
||||||
|
class FailureError(Exception):
|
||||||
|
|
||||||
|
status_code = 400
|
||||||
|
log_message = 'Too much Foo'
|
||||||
|
error_type = 'FailureError'
|
||||||
|
documentation_url = 'http://www.example.com'
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
raise self.FailureError()
|
||||||
|
|
||||||
|
|
||||||
|
class UnexpectedErrorRequestHandler(
|
||||||
|
json_error.JsonErrorMixin, web.RequestHandler):
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
raise Exception()
|
||||||
|
|
||||||
|
|
||||||
|
class TestHTTPError(testing.AsyncHTTPTestCase):
|
||||||
|
|
||||||
|
def get_app(self):
|
||||||
|
return web.Application([('/', HTTPErrorRequestHandler)])
|
||||||
|
|
||||||
|
def test_tornado_thrown_exception(self):
|
||||||
|
response = self.fetch('/')
|
||||||
|
expected = {'message': 'Error Reason', 'type': 'Bad Request'}
|
||||||
|
self.assertEqual(json.loads(response.body), expected)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCustomExceptions(testing.AsyncHTTPTestCase):
|
||||||
|
|
||||||
|
def get_app(self):
|
||||||
|
return web.Application([('/', CustomExceptionRequestHandler)])
|
||||||
|
|
||||||
|
def test_tornado_custom_exception(self):
|
||||||
|
response = self.fetch('/')
|
||||||
|
expected = {
|
||||||
|
'message': 'Too much Foo',
|
||||||
|
'type': 'FailureError',
|
||||||
|
'documentation_url': 'http://www.example.com',
|
||||||
|
}
|
||||||
|
self.assertEqual(json.loads(response.body), expected)
|
||||||
|
|
||||||
|
|
||||||
|
class TestUnexpectedError(testing.AsyncHTTPTestCase):
|
||||||
|
|
||||||
|
def get_app(self):
|
||||||
|
return web.Application([('/', UnexpectedErrorRequestHandler)])
|
||||||
|
|
||||||
|
def test_unexpected_exception(self):
|
||||||
|
response = self.fetch('/')
|
||||||
|
expected = {
|
||||||
|
'message': 'Unexpected Error',
|
||||||
|
'type': 'Internal Server Error'
|
||||||
|
}
|
||||||
|
self.assertEqual(json.loads(response.body), expected)
|
||||||
|
|
Loading…
Reference in a new issue