Invoke after_request on exceptions as well. This fixes #59
This commit is contained in:
parent
ee69fb5890
commit
33e7f2b990
2 changed files with 45 additions and 0 deletions
13
flask.py
13
flask.py
|
|
@ -1362,6 +1362,12 @@ class Flask(_PackageBoundObject):
|
||||||
Then you still have the original application object around and
|
Then you still have the original application object around and
|
||||||
can continue to call methods on it.
|
can continue to call methods on it.
|
||||||
|
|
||||||
|
.. versionchanged:: 0.4
|
||||||
|
The :meth:`after_request` functions are now called even if an
|
||||||
|
error handler took over request processing. This ensures that
|
||||||
|
even if an exception happens database have the chance to
|
||||||
|
properly close the connection.
|
||||||
|
|
||||||
:param environ: a WSGI environment
|
:param environ: a WSGI environment
|
||||||
:param start_response: a callable accepting a status code,
|
:param start_response: a callable accepting a status code,
|
||||||
a list of headers and an optional
|
a list of headers and an optional
|
||||||
|
|
@ -1376,6 +1382,13 @@ class Flask(_PackageBoundObject):
|
||||||
response = self.process_response(response)
|
response = self.process_response(response)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
response = self.make_response(self.handle_exception(e))
|
response = self.make_response(self.handle_exception(e))
|
||||||
|
try:
|
||||||
|
response = self.process_response(response)
|
||||||
|
except Exception, e:
|
||||||
|
self.logger.exception('after_request handler failed '
|
||||||
|
'to postprocess error response. '
|
||||||
|
'Depending on uncertain state?')
|
||||||
|
|
||||||
return response(environ, start_response)
|
return response(environ, start_response)
|
||||||
|
|
||||||
def request_context(self, environ):
|
def request_context(self, environ):
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import sys
|
||||||
import flask
|
import flask
|
||||||
import unittest
|
import unittest
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from logging import StreamHandler
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from werkzeug import parse_date, parse_options_header
|
from werkzeug import parse_date, parse_options_header
|
||||||
|
|
@ -240,6 +241,37 @@ class BasicFunctionalityTestCase(unittest.TestCase):
|
||||||
assert 'after' in evts
|
assert 'after' in evts
|
||||||
assert rv == 'request|after'
|
assert rv == 'request|after'
|
||||||
|
|
||||||
|
def test_after_request_errors(self):
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
called = []
|
||||||
|
@app.after_request
|
||||||
|
def after_request(response):
|
||||||
|
called.append(True)
|
||||||
|
return response
|
||||||
|
@app.route('/')
|
||||||
|
def fails():
|
||||||
|
1/0
|
||||||
|
rv = app.test_client().get('/')
|
||||||
|
assert rv.status_code == 500
|
||||||
|
assert 'Internal Server Error' in rv.data
|
||||||
|
assert len(called) == 1
|
||||||
|
|
||||||
|
def test_after_request_handler_error(self):
|
||||||
|
error_out = StringIO()
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
app.logger.addHandler(StreamHandler(error_out))
|
||||||
|
@app.after_request
|
||||||
|
def after_request(response):
|
||||||
|
1/0
|
||||||
|
return response
|
||||||
|
@app.route('/')
|
||||||
|
def fails():
|
||||||
|
1/0
|
||||||
|
rv = app.test_client().get('/')
|
||||||
|
assert rv.status_code == 500
|
||||||
|
assert 'Internal Server Error' in rv.data
|
||||||
|
assert 'after_request handler failed' in error_out.getvalue()
|
||||||
|
|
||||||
def test_error_handling(self):
|
def test_error_handling(self):
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue