Flask: raising HTTPException does not cause got_request_exception signal to be emitted

Created on 9 Dec 2020  路  2Comments  路  Source: pallets/flask

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.

Expected Behavior

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

Actual Behavior

the signal handler is not called

Environment

  • Python version: 3.8.6 (also tested with 3.7)
  • Flask version: 1.1.2
  • Werkzeug version: 1.0.1
docs

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_exception can mention this config variable as well?

Happy to help with a documentation (or code) change here if the maintainers would like.

All 2 comments

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

Was this page helpful?
0 / 5 - 0 ratings