応答を汎用JSON応答に変更できるグローバルなキャッチオールエラーハンドラーを追加する方法はありますか?
_got_request_exception
_信号は使用できません。応答を変更することが許可されていないためです( http://flask.pocoo.org/docs/0.10/signals/ )。
対照的に、すべてのシグナルハンドラは未定義の順序で実行され、データを変更しません。
_app.handle_exception
_関数は、内部APIのように感じるため、ラップしない方がよいでしょう。私は次のようなことをしていると思います:
_ @app.errorhandler()
def handle_global_error(e):
return "Global error"
_
errorhandler
はパラメーターを受け取らないことに注意してください。つまり、特定のエラーハンドラーが接続されていないすべての例外/ステータスコードをキャッチします。 errorhandler(500)
またはerrorhandler(Exception)
を使用して例外をキャッチできることは知っていますが、たとえばabort(409)
を実行すると、HTML応答が返されます。
@app.errorhandler(Exception)
を使用できます:
デモ(HTTPExceptionチェックにより、ステータスコードが確実に保持されます):
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)
出力:
$ 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"
}
Flask(JSONも返すように)からのデフォルトのHTML例外もオーバーライドする場合は、app.run
の前に次を追加します。
from werkzeug.exceptions import default_exceptions
for ex in default_exceptions:
app.register_error_handler(ex, handle_error)
古いFlaskバージョン(<= 0.10.1、つまり現時点ではgit/master以外のバージョン)の場合、次のコードをアプリケーションに追加してHTTPエラーを明示的に登録します。
from werkzeug import HTTP_STATUS_CODES
for code in HTTP_STATUS_CODES:
app.register_error_handler(code, handle_error)
これはFlask 0.12と互換性があり、問題に対する非常に優れたソリューションです(JSONまたはその他の形式でエラーを表示できます)
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
エレガントとはほど遠いが、以下はHTTPException
のすべてのサブクラスを単一のエラーハンドラに結び付けるために機能する:
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)
これをFlask> = 0.12で実装するよりクリーンな方法は、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, handle_error)
REST api のプレーン(非HTML)エラーページに基づく
コードをまったく変更せずにjsonを返したいので、コードの先頭に次を追加しました
@app.errorhandler(500)
def error_500(exception):
return jsonify({"error": str(exception)}), 500, {'Content-Type': 'application/json'}
@app.errorhandler(400)
def error_400(exception):
return jsonify({"error": str(exception)}), 400, {'Content-Type': 'application/json'}
例外が機能しない場合は、app.register_error_handler(またはapp.errorhandler非装飾的な方法で)