Merge "Serialize WebOb errors as JSON if the client requests it via an Accept header."

This commit is contained in:
Jenkins
2014-06-25 23:10:53 +00:00
committed by Gerrit Code Review
2 changed files with 55 additions and 3 deletions

View File

@@ -1,7 +1,7 @@
try:
from simplejson import loads
except ImportError: # pragma: no cover
from json import loads # noqa
from simplejson import dumps, loads
except ImportError: # pragma: no cover
from json import dumps, loads # noqa
from itertools import chain
from mimetypes import guess_type, add_type
from os.path import splitext
@@ -597,7 +597,22 @@ class PecanBase(object):
except Exception as e:
# if this is an HTTP Exception, set it as the response
if isinstance(e, exc.HTTPException):
# if the client asked for JSON, do our best to provide it
best_match = acceptparse.MIMEAccept(
getattr(req.accept, 'header_value', '*/*')
).best_match(('text/plain', 'text/html', 'application/json'))
state.response = e
if best_match == 'application/json':
json_body = dumps({
'code': e.status_int,
'title': e.title,
'description': e.detail
})
if isinstance(json_body, six.text_type):
e.text = json_body
else:
e.body = json_body
state.response.content_type = best_match
environ['pecan.original_exception'] = e
# if this is not an internal redirect, run error hooks

View File

@@ -8,6 +8,7 @@ else:
import unittest # pragma: nocover
import webob
from webob.exc import HTTPNotFound
from webtest import TestApp
import six
from six import b as b_
@@ -760,6 +761,42 @@ class TestControllerArguments(PecanTestCase):
assert r.body == b_('eater: 10, dummy, day=12, month=1')
class TestDefaultErrorRendering(PecanTestCase):
def test_plain_error(self):
class RootController(object):
pass
app = TestApp(Pecan(RootController()))
r = app.get('/', status=404)
assert r.status_int == 404
assert r.content_type == 'text/plain'
assert r.body == b_(HTTPNotFound().plain_body({}))
def test_html_error(self):
class RootController(object):
pass
app = TestApp(Pecan(RootController()))
r = app.get('/', headers={'Accept': 'text/html'}, status=404)
assert r.status_int == 404
assert r.content_type == 'text/html'
assert r.body == b_(HTTPNotFound().html_body({}))
def test_json_error(self):
class RootController(object):
pass
app = TestApp(Pecan(RootController()))
r = app.get('/', headers={'Accept': 'application/json'}, status=404)
assert r.status_int == 404
json_resp = json.loads(r.body.decode())
assert json_resp['code'] == 404
assert json_resp['description'] is None
assert json_resp['title'] == 'Not Found'
assert r.content_type == 'application/json'
class TestAbort(PecanTestCase):
def test_abort(self):