Browse Source

Merge pull request #2013 from pallets/bugfix/error-handler-error-handler

Corrected after response for error handlers
pull/2022/head
Armin Ronacher 8 years ago committed by GitHub
parent
commit
9e41eca7f8
  1. 2
      CHANGES
  2. 25
      flask/app.py
  3. 23
      tests/test_basic.py

2
CHANGES

@ -15,6 +15,8 @@ Version 0.12
(pull request ``#1730``). (pull request ``#1730``).
- Revert a behavior change that made the dev server crash instead of returning - Revert a behavior change that made the dev server crash instead of returning
a Internal Server Error (pull request ``#2006``). a Internal Server Error (pull request ``#2006``).
- Correctly invoke response handlers for both regular request dispatching as
well as error handlers.
Version 0.11.2 Version 0.11.2
-------------- --------------

25
flask/app.py

@ -1555,7 +1555,7 @@ class Flask(_PackageBoundObject):
self.log_exception((exc_type, exc_value, tb)) self.log_exception((exc_type, exc_value, tb))
if handler is None: if handler is None:
return InternalServerError() return InternalServerError()
return handler(e) return self.finalize_request(handler(e), from_error_handler=True)
def log_exception(self, exc_info): def log_exception(self, exc_info):
"""Logs an exception. This is called by :meth:`handle_exception` """Logs an exception. This is called by :meth:`handle_exception`
@ -1623,9 +1623,30 @@ class Flask(_PackageBoundObject):
rv = self.dispatch_request() rv = self.dispatch_request()
except Exception as e: except Exception as e:
rv = self.handle_user_exception(e) rv = self.handle_user_exception(e)
return self.finalize_request(rv)
def finalize_request(self, rv, from_error_handler=False):
"""Given the return value from a view function this finalizes
the request by converting it into a repsonse and invoking the
postprocessing functions. This is invoked for both normal
request dispatching as well as error handlers.
Because this means that it might be called as a result of a
failure a special safe mode is available which can be enabled
with the `from_error_handler` flag. If enabled failures in
response processing will be logged and otherwise ignored.
:internal:
"""
response = self.make_response(rv) response = self.make_response(rv)
try:
response = self.process_response(response) response = self.process_response(response)
request_finished.send(self, response=response) request_finished.send(self, response=response)
except Exception:
if not from_error_handler:
raise
self.logger.exception('Request finalizing failed with an '
'error while handling an error')
return response return response
def try_trigger_before_first_request_functions(self): def try_trigger_before_first_request_functions(self):
@ -1972,7 +1993,7 @@ class Flask(_PackageBoundObject):
response = self.full_dispatch_request() response = self.full_dispatch_request()
except Exception as e: except Exception as e:
error = e error = e
response = self.make_response(self.handle_exception(e)) response = self.handle_exception(e)
return response(environ, start_response) return response(environ, start_response)
finally: finally:
if self.should_ignore_error(error): if self.should_ignore_error(error):

23
tests/test_basic.py

@ -768,6 +768,29 @@ def test_error_handling():
assert b'forbidden' == rv.data assert b'forbidden' == rv.data
def test_error_handling_processing():
app = flask.Flask(__name__)
app.config['LOGGER_HANDLER_POLICY'] = 'never'
@app.errorhandler(500)
def internal_server_error(e):
return 'internal server error', 500
@app.route('/')
def broken_func():
1 // 0
@app.after_request
def after_request(resp):
resp.mimetype = 'text/x-special'
return resp
with app.test_client() as c:
resp = c.get('/')
assert resp.mimetype == 'text/x-special'
assert resp.data == b'internal server error'
def test_before_request_and_routing_errors(): def test_before_request_and_routing_errors():
app = flask.Flask(__name__) app = flask.Flask(__name__)

Loading…
Cancel
Save