2015-03-29 9 views
16

Gibt es eine Möglichkeit, einen globalen Catch-All-Fehlerhandler hinzuzufügen, in dem ich die Antwort auf eine generische JSON-Antwort ändern kann?Globaler Fehlerhandler für jede Ausnahme

Ich kann das Signal got_request_exception nicht verwenden, da die Antwort nicht geändert werden darf (http://flask.pocoo.org/docs/0.10/signals/).

Im Gegensatz dazu werden alle Signalhandler in nicht definierter Reihenfolge ausgeführt und verändern keine Daten.

Ich würde es vorziehen, nicht die app.handle_exception-Funktion als das Gefühl wie interne API wickeln. Ich glaube, ich bin nach so etwas wie:

@app.errorhandler() 
def handle_global_error(e): 
    return "Global error" 

Notiere die errorhandler keine Parameter nehmen, was bedeutet, es würde alle Ausnahmen/Statuscodes fangen, die nicht einen bestimmten Fehler-Handler an ihnen hat. Ich weiß, dass ich errorhandler(500) oder errorhandler(Exception) verwenden kann, um Ausnahmen zu fangen, aber wenn ich zum Beispiel abort(409) mache, wird es immer noch eine HTML-Antwort zurückgeben.

Antwort

24

können Sie @app.errorhandler(Exception) verwenden:

Demo (die Httpexception Prüfung stellt sicher, dass der Statuscode erhalten):

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) 

Ausgang:

$ 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" 
} 

Wenn Sie auch die außer Kraft setzen möchten, Standard-HTML-Ausnahmen von Flask (so dass sie auch JSON zurückgeben), fügen Sie Folgendes vor app.run:

hinzu
from werkzeug.exceptions import default_exceptions 
for ex in default_exceptions: 
    app.register_error_handler(ex, handle_error) 

Für ältere Versionen Flask (< = 0.10.1, dh jede nicht-git/Master-Version im Moment), fügen Sie den folgenden Code in Ihre Anwendung die HTTP-Fehler explizit registrieren:

from werkzeug import HTTP_STATUS_CODES 
for code in HTTP_STATUS_CODES: 
    app.register_error_handler(code, handle_error) 
+0

Das ist so seltsam. Ich kopiere deinen Code in eine Python-Shell mit Flask 0.10.1 und bekomme trotzdem HTML-Fehler, wenn ich diese Endpunkte mit curl anfordere. Welche Version von Flask benutzt du? – joscarsson

+0

Ah, anscheinend hat sich etwas zwischen 0.10.1 und der Version von git geändert, mit der ich es getestet habe. – ThiefMaster

+0

https://github.com/mitsuhoho/flask/blob/0.10.1/flask/app.py#L1086 - anscheinend verwendet es nur den Code der Ausnahme in älteren Versionen. – ThiefMaster

4

Weit davon entfernt, elegant, aber die folgenden Werke für alle Subklassen von HTTPException auf einen einzigen Fehlerhandler binden:

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) 
9

Dies ist Flask 0.12 kompatibel, und eine sehr gute Lösung für das Problem (es erlaubt es, ren der Fehler in JSON oder einem anderen 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

+0

danke. dieser hat funktioniert. – JSBach

Verwandte Themen