Is there a way to add a global catch-all error handler in which I can change the response to a generic JSON response?
I can't use the got_request_exception
signal, as it is not allowed to modify the response (http://flask.pocoo.org/docs/0.10/signals/).
In contrast all signal handlers are executed in undefined order and do not modify any data.
I would prefer to not wrap the app.handle_exception
function as that feels like internal API. I guess I'm after something like:
@app.errorhandler() def handle_global_error(e): return "Global error"
Note the errorhandler
does not take any parameters, meaning it would catch all exceptions/status codes which does not have a specific error handler attached to them. I know I can use errorhandler(500)
or errorhandler(Exception)
to catch exceptions, but if I do abort(409)
for example, it will still return a HTML response.
The Global Exception Handler is a type of workflow designed to determine the project's behavior when encountering an execution error. Only one Global Exception Handler can be set per automation project.
An exception handler is code that stipulates what a program will do when an anomalous event disrupts the normal flow of that program's instructions. An exception, in a computer context, is an unplanned event that occurs while a program is executing and disrupts the flow of its instructions.
The @ControllerAdvice is an annotation, to handle the exceptions globally.
You can use @app.errorhandler(Exception)
:
Demo (the HTTPException check ensures that the status code is preserved):
from flask import Flask, abort, jsonify from werkzeug.exceptions import HTTPException app = Flask('test') @app.errorhandler(Exception) def handle_error(e): code = 500 if isinstance(e, HTTPException): code = e.code return jsonify(error=str(e)), code @app.route('/') def index(): abort(409) app.run(port=1234)
Output:
$ http get http://127.0.0.1:1234/ HTTP/1.0 409 CONFLICT Content-Length: 31 Content-Type: application/json Date: Sun, 29 Mar 2015 17:06:54 GMT Server: Werkzeug/0.10.1 Python/3.4.3 { "error": "409: Conflict" } $ http get http://127.0.0.1:1234/notfound HTTP/1.0 404 NOT FOUND Content-Length: 32 Content-Type: application/json Date: Sun, 29 Mar 2015 17:06:58 GMT Server: Werkzeug/0.10.1 Python/3.4.3 { "error": "404: Not Found" }
If you also want to override the default HTML exceptions from Flask (so that they also return JSON), add the following before app.run
:
from werkzeug.exceptions import default_exceptions for ex in default_exceptions: app.register_error_handler(ex, handle_error)
For older Flask versions (<=0.10.1, i.e. any non-git/master version at the moment), add the following code to your application to register the HTTP errors explicitly:
from werkzeug import HTTP_STATUS_CODES for code in HTTP_STATUS_CODES: app.register_error_handler(code, handle_error)
This is Flask 0.12 compatible, and a very good solution to the problem (it allows one to render errors in JSON or any other format)
from functools import wraps from flask import Flask, redirect, jsonify app = Flask(__name__) def get_http_exception_handler(app): """Overrides the default http exception handler to return JSON.""" handle_http_exception = app.handle_http_exception @wraps(handle_http_exception) def ret_val(exception): exc = handle_http_exception(exception) return jsonify({'code':exc.code, 'message':exc.description}), exc.code return ret_val # Override the HTTP exception handler. app.handle_http_exception = get_http_exception_handler(app)
https://github.com/pallets/flask/issues/671#issuecomment-12746738
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With