Skip to content

Commit 9cd32ca

Browse files
committed
Corrected after response for error handlers
Before this change after request functions were not correctly invoked for error handlers.
1 parent dbcd64e commit 9cd32ca

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Version 0.12
1515
(pull request ``#1730``).
1616
- Revert a behavior change that made the dev server crash instead of returning
1717
a Internal Server Error (pull request ``#2006``).
18+
- Correctly invoke response handlers for both regular request dispatching as
19+
well as error handlers.
1820

1921
Version 0.11.2
2022
--------------

flask/app.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,7 +1555,7 @@ def handle_exception(self, e):
15551555
self.log_exception((exc_type, exc_value, tb))
15561556
if handler is None:
15571557
return InternalServerError()
1558-
return handler(e)
1558+
return self.finalize_request(handler(e), from_error_handler=True)
15591559

15601560
def log_exception(self, exc_info):
15611561
"""Logs an exception. This is called by :meth:`handle_exception`
@@ -1623,9 +1623,30 @@ def full_dispatch_request(self):
16231623
rv = self.dispatch_request()
16241624
except Exception as e:
16251625
rv = self.handle_user_exception(e)
1626+
return self.finalize_request(rv)
1627+
1628+
def finalize_request(self, rv, from_error_handler=False):
1629+
"""Given the return value from a view function this finalizes
1630+
the request by converting it into a repsonse and invoking the
1631+
postprocessing functions. This is invoked for both normal
1632+
request dispatching as well as error handlers.
1633+
1634+
Because this means that it might be called as a result of a
1635+
failure a special safe mode is available which can be enabled
1636+
with the `from_error_handler` flag. If enabled failures in
1637+
response processing will be logged and otherwise ignored.
1638+
1639+
:internal:
1640+
"""
16261641
response = self.make_response(rv)
1627-
response = self.process_response(response)
1628-
request_finished.send(self, response=response)
1642+
try:
1643+
response = self.process_response(response)
1644+
request_finished.send(self, response=response)
1645+
except Exception:
1646+
if not from_error_handler:
1647+
raise
1648+
self.logger.exception('Request finalizing failed with an '
1649+
'error while handling an error')
16291650
return response
16301651

16311652
def try_trigger_before_first_request_functions(self):
@@ -1972,7 +1993,7 @@ def wsgi_app(self, environ, start_response):
19721993
response = self.full_dispatch_request()
19731994
except Exception as e:
19741995
error = e
1975-
response = self.make_response(self.handle_exception(e))
1996+
response = self.handle_exception(e)
19761997
return response(environ, start_response)
19771998
finally:
19781999
if self.should_ignore_error(error):

tests/test_basic.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,29 @@ def error2():
768768
assert b'forbidden' == rv.data
769769

770770

771+
def test_error_handling_processing():
772+
app = flask.Flask(__name__)
773+
app.config['LOGGER_HANDLER_POLICY'] = 'never'
774+
775+
@app.errorhandler(500)
776+
def internal_server_error(e):
777+
return 'internal server error', 500
778+
779+
@app.route('/')
780+
def broken_func():
781+
1 // 0
782+
783+
@app.after_request
784+
def after_request(resp):
785+
resp.mimetype = 'text/x-special'
786+
return resp
787+
788+
with app.test_client() as c:
789+
resp = c.get('/')
790+
assert resp.mimetype == 'text/x-special'
791+
assert resp.data == b'internal server error'
792+
793+
771794
def test_before_request_and_routing_errors():
772795
app = flask.Flask(__name__)
773796

0 commit comments

Comments
 (0)