Gestionnaire d'erreurs Global pour toute exception
Existe-t-il un moyen d'ajouter un gestionnaire d'erreurs global catch-all dans lequel je peux changer la réponse en une réponse JSON Générique?
Je ne peux pas utiliser le signal got_request_exception
, car il n'est pas autorisé à modifier la réponse ( http://flask.pocoo.org/docs/0.10/signals/).
En revanche, tous les gestionnaires de signaux sont exécutés dans un ordre indéfini et ne modifient aucune donnée.
Je préférerais ne pas envelopper la fonction app.handle_exception
car cela ressemble à une API interne. Je suppose que je suis après quelque chose comme:
@app.errorhandler()
def handle_global_error(e):
return "Global error"
Notez que le errorhandler
ne prend aucun paramètre, ce qui signifie qu'il attraperait tous les codes d'exception / statut qui n'ont pas de gestionnaire d'erreur spécifique attaché à eux. Je sais que je peux utiliser errorhandler(500)
ou errorhandler(Exception)
pour attraper des exceptions, mais si je le fais abort(409)
par exemple, il retournera toujours une réponse HTML.
5 réponses
, Vous pouvez utiliser @app.errorhandler(Exception)
:
Démo (la vérification HTTPException garantit que le code d'état est conservé):
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)
Sortie:
$ 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"
}
Si vous souhaitez également remplacer les exceptions HTML par défaut de Flask (afin qu'elles renvoient également JSON), ajoutez ce qui suit avant app.run
:
from werkzeug.exceptions import default_exceptions
for ex in default_exceptions:
app.register_error_handler(ex, handle_error)
Pour les anciennes versions de Flask (
from werkzeug import HTTP_STATUS_CODES
for code in HTTP_STATUS_CODES:
app.register_error_handler(code, handle_error)
Ceci est compatible Flask 0.12, et une très bonne solution au problème (elle permet de rendre des erreurs en JSON ou tout autre 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
Loin d'être élégant, mais ce qui suit fonctionne pour lier toutes les sous-classes de HTTPException
à un seul gestionnaire d'erreur:
from flask import jsonify
from werkzeug.exceptions import HTTPException
def handle_error(error):
code = 500
if isinstance(error, HTTPException):
code = error.code
return jsonify(error='error', code=code)
for cls in HTTPException.__subclasses__():
app.register_error_handler(cls, handle_error)
Si les Exceptions ne fonctionnent pas, vous pouvez essayer l'application .register_error_handler (ou utilisez l'application .errorhandler de manière non décoratrice)
Une façon plus propre de l'implémenter dans Flask > = 0.12 serait d'enregistrer explicitement le gestionnaire pour chaque exception Werkzeug:
from flask import jsonify
from werkzeug.exceptions import HTTPException, default_exceptions
app = Flask('test')
def handle_error(error):
code = 500
if isinstance(error, HTTPException):
code = error.code
return jsonify(error='error', code=code)
for exc in default_exceptions:
app.register_error_handler(exc, error_handler)