概要
APIの前処理・後処理をデコレーターで書くためのライブラリ。
下記の @require_privilege
のようなデコレーターを作るためのヘルパークラス。
@app.delete('/user/{user_id}')
@require_privilege('admin')
def delete_user(user_id: str):
# ユーザーを削除する処理
...
動機
複数のエンドポイントに共通する仕様をデコレーターで宣言的に表現したかった。
Web APIを作っていると以下のような仕様を持つエンドポイントが出てくることがよくある。
- 管理者ユーザー以外のリクエストにはステータスコード403を返す
- エンドポイントがステータスコード200を返す場合、ヘッダーに
Cache-Control max-age
を追加する
共通の仕様を持つエンドポイントだけに適用される前処理・後処理を書きたいが、FastAPIにはその仕組みがない。
middlewareで前処理・後処理を書くことができるが、middlewareだと全てのリクエストに適用されるため、エンドポイント毎に適用するしないを分けられない。
ライブラリの使い方
デコレーターを定義する
from fastapi_decorator_helper import DecoratorHelper, ExecutePathOperator
def require_permission(name):
# ヘルパーのインスタンスを生成
helper = DecoratorHelper()
# デコレーターをラップする
@helper.wraps
def wrapper(request: Request, next: ExecutePathOperator):
# ユーザーが権限を持つかチェックするコードをここに書く
...
# パスオペレーションを実行する
return next()
return wrapper
デコレーターはRequestオブジェクトやパスパラメータ等、パスオペレーションと同様の引数を受け取れる。
パスオペレーションにデコレーターを付ける
@app.delete('/user/{user_id}')
@require_privilege('admin')
def delete_user(user_id: str):
# ユーザーを削除する処理
...
おわり。
今後の機能追加案
デコレーターでdocstringを拡張できると便利かもしれない。
以下のように使う。
def allow_cache(max_age):
helper = DecoratorHelper()
@helper.wraps
def wrapper(next: ExecutePathOperator):
...
# ★docstringに情報を追記できる★
helper.extend_document(f'''
このエンドポイントがステータスコード200を返す場合、クライアントはレスポンスをキャッシュできる。
max-ageは{max_age}。
''')
return wrapper
APIの仕様をデコレーターで表現するため、その仕様がOpenAPIのドキュメントに反映されるとうれしい。