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)
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``
------------------------------------------

View File

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

View File

@@ -1,5 +1,8 @@
import json
from webtest import TestApp
import pecan
from pecan.middleware.errordocument import ErrorDocumentMiddleware
from pecan.middleware.recursive import RecursiveMiddleware
from pecan.tests import PecanTestCase
@@ -52,3 +55,36 @@ class TestErrorDocumentMiddleware(PecanTestCase):
assert r.status_int == 404
assert r.body == ('Error: 404 Not Found. '
'(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!'