API に対する過剰なリクエストを防ぐため、レートリミット(流量制限)を実装することは重要である。Flask-Limiter を使えば簡単にレートリミットを導入できる。
Flask-Limiter のセットアップ
pip install flask-limiter
from flask import Flask from flask_limiter import Limiter from flask_limiter.util import get_remote_address app = Flask(__name__) limiter = Limiter( key_func=get_remote_address, app=app, default_limits=['200 per day', '50 per hour'] )
key_func はリクエストを識別するキーを返す関数である。IP アドレスでの制限が一般的だが、認証済みユーザーの ID を使うこともできる。
エンドポイント単位の制限
@app.route('/api/search') @limiter.limit('10 per minute') def search(): return {'results': []} @app.route('/api/login', methods=['POST']) @limiter.limit('5 per minute') def login(): return {'status': 'ok'}
制限の書式
| 10 per minute | 1分間に10リクエスト |
| 100 per hour | 1時間に100リクエスト |
| 1000 per day | 1日に1000リクエスト |
| 1 per second | 1秒に1リクエスト |
複数の制限を組み合わせることもできる。
@app.route('/api/data') @limiter.limit('100 per hour') @limiter.limit('10 per minute') def data(): return {'data': 'value'}
動的なキー関数
ログインユーザーごとに制限する場合。
def get_user_id(): if hasattr(g, 'user') and g.user: return str(g.user.id) return get_remote_address() limiter = Limiter(key_func=get_user_id, app=app)
特定のユーザーを除外
@app.route('/api/data') @limiter.limit('10 per minute') @limiter.exempt def data(): # このエンドポイントは制限なし return {'data': 'value'} # または条件付きで除外 def whitelist_check(): return g.user and g.user.is_admin @app.route('/api/admin') @limiter.limit('10 per minute', exempt_when=whitelist_check) def admin(): return {'admin': 'data'}
Redis をストレージに使う
デフォルトではメモリ内にカウントを保持するが、本番では Redis を使う。
from flask_limiter import Limiter from flask_limiter.util import get_remote_address app.config['RATELIMIT_STORAGE_URI'] = 'redis://localhost:6379' limiter = Limiter( key_func=get_remote_address, app=app, storage_uri='redis://localhost:6379' )
エラーレスポンスのカスタマイズ
@app.errorhandler(429) def ratelimit_error(e): return { 'error': 'Too many requests', 'retry_after': e.description }, 429
ヘッダーの確認
レートリミットの状態はレスポンスヘッダーで確認できる。
| X-RateLimit-Limit | 制限数 |
| X-RateLimit-Remaining | 残りリクエスト数 |
| X-RateLimit-Reset | リセット時刻 |
| Retry-After | 再試行までの秒数(429 時) |
レートリミットは API の安定性を保ち、悪意のあるリクエストからシステムを守るために重要である。