1
0

More than 1 year has passed since last update.

FastAPIのパスオペレーションに前処理・後処理を書くためのライブラリを作った

Last updated at Posted at 2022-12-26

概要

fastapi-decorator-helper

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のドキュメントに反映されるとうれしい。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0