Merge "Serialize WebOb errors as JSON if the client requests it via an Accept header."
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user