Skip to content

ミドルウェア

ミドルウェアは、リクエストがエンドポイントに届く前と、レスポンスがクライアントに返る前に処理を挟み込める仕組み。
認証チェックや CORS、 CSRF 対策 のように、複数のエンドポイントに共通でかけたい処理を書くのに向いてる。

cf. https://fastapi.tiangolo.com/tutorial/middleware/


どういう流れで動くのか

ミドルウェアは「リクエストを受け取る → 次の処理に渡す → レスポンスを受け取る」という順番で動く。
call_next を呼ぶと、その先のミドルウェアやエンドポイントに処理が渡って、戻ってきたレスポンスを受け取れる。

下の例は、リクエストの処理にかかった時間を測ってレスポンスヘッダーに入れるミドルウェア( FastAPI チュートリアルと同じもの )。

# main.py
import time
from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start = time.perf_counter()
    response = await call_next(request)  # 先の処理にリクエストを渡す
    elapsed = time.perf_counter() - start
    response.headers["X-Process-Time"] = str(elapsed)  # 返ってきたレスポンスに手を加える
    return response

@app.middleware("http") を付けると、全リクエストがこの関数を通る。引数の request が届いたリクエストで、 call_next が「この先の処理を実行して」という関数。

ポイントは call_next を境に処理が「行き」と「帰り」に分かれること。

  • 行き( call_next の前 ): まだエンドポイントには渡してない段階。ここでは開始時刻を記録してる。
  • await call_next(request) : ここで初めてエンドポイントに処理が渡る。 await で処理が終わるのを待って、結果のレスポンスを受け取る。
  • 帰り( call_next の後 ): 返ってきたレスポンスに手を加えられる。ここではかかった時間を計算して、 X-Process-Time ヘッダーに入れてる。

認証チェックみたいに「エンドポイントに入る前に弾きたい」処理は行きに、レスポンスの加工は帰りに書く、というイメージ。

複数のミドルウェアを登録すると、玉ねぎのように外側から内側へ入って、内側から外側へ戻ってくる。


FastAPI の内部の仕組み

ミドルウェアが内部でどう動いてるかは、 Marcelo Trylesinski さんの PyCon Italia 2024 のトークで説明されてる。