Raising a HTTPException (for example by calling abort()) does not cause registered signal handlers for got_request_exception to be called.
https://flask.palletsprojects.com/en/1.1.x/api/#flask.got_request_exception does not state that some Exceptions
are forwarded to the handler and some are not.
Changing this behaviour could potentially break quite a few application, but at least the signal documentation should include this behaviour.
raising a HTTPException in a view function should cause the signal handler to be called.
from flask import Flask, got_request_exception, abort
app = Flask(__name__)
def signal_handler(sender, exception, **extra):
print("handled %s" % str(type(exception)))
got_request_exception.connect(signal_handler)
@app.route('/1')
def view_1():
# calling this view prints "handled <class 'RuntimeError'>" to the console
raise RuntimeError()
@app.route('/2')
def view_2():
# calling this view prints nothing
abort(400)
# raise werkzeug.exception.TooManyRequests
# e.g. also does nothing
the signal handler is not called
Nice find.
It seems to me that the "fix" here is an update in documentation, something like adding the extra info mentioning HTTPException isn't recorded:
"This signal is sent when a non Werkzeug.exceptions.HTTPException exception happens during request processing. It is sent before the standard exception handling kicks in and even in debug mode, where no exception handling happens. The exception itself is passed to the subscriber as exception."
What I think is happening here is Flask (and the contributors) consider HTTPExceptions (Bad Request, GatewayTimeout, etc.) as recoverable for the Flask application -- they only affect a single request and are often expected (in the case of bad authn, rate-limiting) and thrown by the application writer, whereas Runtime errors indicate a more serious problem with the WSGI server/app that may cause it to crash/exit.
For more context,
HTTPException handling logic is explicitly handled differently:
It seems that if you want to enable the behavior you mention or at least treat HTTPExceptions more similarly to other Python exceptions, setting TRAP_HTTP_EXCEPTIONS in config is what you want. Maybe the docs for got_request_exception can mention this config variable as well?
Happy to help with a documentation (or code) change here if the maintainers would like.
@tonydelanuez happy to review a PR if you still have time
Most helpful comment
Nice find.
It seems to me that the "fix" here is an update in documentation, something like adding the extra info mentioning HTTPException isn't recorded:
"This signal is sent when a non Werkzeug.exceptions.HTTPException exception happens during request processing. It is sent before the standard exception handling kicks in and even in debug mode, where no exception handling happens. The exception itself is passed to the subscriber as exception."
What I think is happening here is Flask (and the contributors) consider HTTPExceptions (Bad Request, GatewayTimeout, etc.) as recoverable for the Flask application -- they only affect a single request and are often expected (in the case of bad authn, rate-limiting) and thrown by the application writer, whereas Runtime errors indicate a more serious problem with the WSGI server/app that may cause it to crash/exit.
For more context,
HTTPException handling logic is explicitly handled differently:
It seems that if you want to enable the behavior you mention or at least treat HTTPExceptions more similarly to other Python exceptions, setting TRAP_HTTP_EXCEPTIONS in config is what you want. Maybe the docs for
got_request_exceptioncan mention this config variable as well?Happy to help with a documentation (or code) change here if the maintainers would like.