Store exceptions raised by `abort` in the WSGI environ.

This makes it easier to access the original exception later in the request cycle (e.g., other middleware or in custom error handlers).
This commit is contained in:
Ryan Petrello
2013-04-09 14:00:16 -04:00
parent c3339f2755
commit b5d69b5624
3 changed files with 44 additions and 0 deletions

View File

@@ -163,6 +163,13 @@ Pecan also comes with ``abort``, a utility function for raising HTTP errors:
abort(404) abort(404)
Under the hood, ``abort`` raises an instance of
``webob.exc.WSGIHTTPException`` which is used by pecan to render default
response bodies for HTTP errors. This exception is stored in the WSGI request
environ at ``pecan.original_exception``, where it can be accessed later in the
request cycle (by, for example, other middleware or :ref:`errors`).
Routing to Subcontrollers with ``_lookup`` Routing to Subcontrollers with ``_lookup``
------------------------------------------ ------------------------------------------

View File

@@ -545,6 +545,7 @@ class Pecan(object):
# if this is an HTTP Exception, set it as the response # if this is an HTTP Exception, set it as the response
if isinstance(e, exc.HTTPException): if isinstance(e, exc.HTTPException):
state.response = e state.response = e
environ['pecan.original_exception'] = e
# if this is not an internal redirect, run error hooks # if this is not an internal redirect, run error hooks
if not isinstance(e, ForwardRequestException): if not isinstance(e, ForwardRequestException):

View File

@@ -1,5 +1,8 @@
import json
from webtest import TestApp from webtest import TestApp
import pecan
from pecan.middleware.errordocument import ErrorDocumentMiddleware from pecan.middleware.errordocument import ErrorDocumentMiddleware
from pecan.middleware.recursive import RecursiveMiddleware from pecan.middleware.recursive import RecursiveMiddleware
from pecan.tests import PecanTestCase from pecan.tests import PecanTestCase
@@ -52,3 +55,36 @@ class TestErrorDocumentMiddleware(PecanTestCase):
assert r.status_int == 404 assert r.status_int == 404
assert r.body == ('Error: 404 Not Found. ' assert r.body == ('Error: 404 Not Found. '
'(Error page could not be fetched)') '(Error page could not be fetched)')
def test_original_exception(self):
class RootController(object):
@pecan.expose()
def index(self):
if pecan.request.method != 'POST':
pecan.abort(405, 'You have to POST, dummy!')
return 'Hello, World!'
@pecan.expose('json')
def error(self, status):
return dict(
status=int(status),
reason=pecan.request.environ[
'pecan.original_exception'
].detail
)
app = pecan.Pecan(RootController())
app = RecursiveMiddleware(ErrorDocumentMiddleware(app, {
405: '/error/405'
}))
app = TestApp(app)
assert app.post('/').status_int == 200
r = app.get('/', expect_errors=405)
assert r.status_int == 405
resp = json.loads(r.body)
assert resp['status'] == 405
assert resp['reason'] == 'You have to POST, dummy!'