Flask ではリクエスト処理の前後にフック関数を実行できる。before_request と after_request を使うことで、認証チェック、ロギング、レスポンスの加工などを一元的に処理できる。
リクエストライフサイクル
Flask のリクエスト処理は以下の順序で実行される。
before_request 関数(複数可)
ビュー関数
after_request 関数(複数可)
teardown_request 関数(複数可)
before_request
リクエスト処理の前に実行される。戻り値があれば、ビュー関数は実行されずその値がレスポンスになる。
from flask import Flask, g, request, session
app = Flask(__name__)
@app.before_request
def load_user():
g.user = None
if 'user_id' in session:
g.user = User.query.get(session['user_id'])
@app.before_request
def require_login():
# 特定のエンドポイントは認証必須
if request.endpoint in ['profile', 'settings']:
if g.user is None:
return redirect(url_for('login'))
複数の before_request は登録順に実行される。
after_request
レスポンス生成後に実行される。レスポンスオブジェクトを受け取り、加工して返す。
@app.after_request
def add_header(response):
response.headers['X-Frame-Options'] = 'DENY'
response.headers['X-Content-Type-Options'] = 'nosniff'
return response
@app.after_request
def log_response(response):
app.logger.info(f'{request.method} {request.path} -> {response.status_code}')
return response
after_request は登録の逆順で実行される。必ずレスポンスを返すこと。
teardown_request
リクエスト処理の最後に必ず実行される。例外が発生しても実行されるため、リソースのクリーンアップに使う。
@app.teardown_request
def close_db_connection(exception):
db = g.pop('db', None)
if db is not None:
db.close()
引数 exception には例外オブジェクトが渡される(例外がなければ None)。
Blueprint でのフック
Blueprint にもフックを登録できる。Blueprint のフックはその Blueprint 内のルートにのみ適用される。
from flask import Blueprint
api_bp = Blueprint('api', __name__)
@api_bp.before_request
def api_auth():
# API Blueprint 内のリクエストのみ認証チェック
token = request.headers.get('Authorization')
if not verify_token(token):
return jsonify({'error': 'Unauthorized'}), 401
アプリ全体 vs Blueprint
| @app.before_request | すべてのリクエストに適用 |
| @bp.before_request | その Blueprint 内のリクエストのみ |
| @app.before_request_funcs[None] | 内部的なリストに直接登録 |
実行順序の詳細
# 登録順
@app.before_request
def first(): print('1')
@app.before_request
def second(): print('2')
# 実行結果: 1, 2(登録順)
@app.after_request
def after_first(r): print('A'); return r
@app.after_request
def after_second(r): print('B'); return r
# 実行結果: B, A(逆順)
フックの実行順序を把握しておくことで、複雑な前処理・後処理を正しく設計できる。