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.

26
demandé sur Sharadh 2015-03-29 19:58:14

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)
33
répondu ThiefMaster 2017-12-19 19:06:40

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

9
répondu lol 2017-05-21 11:55:46

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)
5
répondu bwind 2017-01-16 08:16:38

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)

Source: https://github.com/pallets/flask/issues/1837

0
répondu Suresh Ghanta 2018-03-30 07:26:43

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)
0
répondu nfvs 2018-08-06 09:49:47