summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan LaCour <jonathan@cleverdevil.org>2013-04-12 11:56:56 -0700
committerJonathan LaCour <jonathan@cleverdevil.org>2013-04-12 11:56:56 -0700
commit0f94eea7a301ae5493097145700aba98f932fa3e (patch)
tree4f84e4ee1ac1fb1c42d4a14152a5a1b0cc330ab6
parentc3339f27552f38f16ad74e0f9da2da198cb8585a (diff)
parentb5d69b5624f3e359c3c0c898e2b2dd23f85af01b (diff)
downloadpecan-0f94eea7a301ae5493097145700aba98f932fa3e.tar.gz
Merge pull request #206 from ryanpetrello/next
Store exceptions raised by ``abort`` in the WSGI environ.
-rw-r--r--docs/source/routing.rst7
-rw-r--r--pecan/core.py1
-rw-r--r--pecan/tests/middleware/test_errordocument.py36
3 files changed, 44 insertions, 0 deletions
diff --git a/docs/source/routing.rst b/docs/source/routing.rst
index e27baf6..6ed3524 100644
--- a/docs/source/routing.rst
+++ b/docs/source/routing.rst
@@ -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``
------------------------------------------
diff --git a/pecan/core.py b/pecan/core.py
index 5897988..e4fdd99 100644
--- a/pecan/core.py
+++ b/pecan/core.py
@@ -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):
diff --git a/pecan/tests/middleware/test_errordocument.py b/pecan/tests/middleware/test_errordocument.py
index 92c4c08..c4faa42 100644
--- a/pecan/tests/middleware/test_errordocument.py
+++ b/pecan/tests/middleware/test_errordocument.py
@@ -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!'