スポンサーリンク

FastAPI の Header とは何か?仕組みから理解する

記事内に広告が含まれています。

FastAPI を触っていると、こんなコードに出会います。

from typing import Annotated
from fastapi import FastAPI, Header

app = FastAPI()

@app.get("/items")
async def read_items(
    user_agent: Annotated[str | None, Header()] = None
):
    return {"User-Agent": user_agent}

これを見たとき、私はこう感じました。

  • Header() って何?
  • なぜ引数に書くだけでヘッダーが取得できるの?
  • @app.get() と何か関係ある?
  • デコレーターが特別なことをしている?

この記事では、どう動いているのか、分解してみたいと思います。


スポンサーリンク

結論

FastAPI が、関数を呼び出す前にHTTP ヘッダーを読み取る処理を自動で差し込んでいる

関数はヘッダーを読んでいません。

FastAPI が読んでから渡しています。


スポンサーリンク

Header() はデコレーターではない

重要なポイント。

Header()

はデコレーターではありません。

これはただの「設定オブジェクト」を返す関数で、

「この引数は HTTP ヘッダーから取得してね」

と FastAPI に伝えているだけです。


@app.get() がサーバー起動時にしていること

@app.get() は単にルーティングを登録しているだけではありません。

サーバー起動時に、次のことをしています。

  1. 関数の引数(シグネチャ)を読み取る
  2. 型ヒントを確認する
  3. Header() が付いていることを見つける
  4. 「この引数はヘッダーから取得する」と記録する

この時点ではまだヘッダーは見ていません。

「どう処理するかの設計図」を作っているだけです。


リクエスト時に実際に起きること

リクエストが来ると、FastAPI はあなたの関数をそのまま呼びません。

内部で生成した「ラッパー関数」が先に実行されます。

そのラッパー関数がやっていることは、概念的には次のような処理です。

# ① ヘッダーを読む
value = request.headers.get("user-agent")

# ② 型チェックやバリデーション

# ③ あなたの関数を呼び出す
await read_items(user_agent=value)

つまり、

ヘッダーの判定は、デコレートされた結果できた処理の中で行われる

あなたの関数の中ではありません。


Header() を外すとどうなるか

@app.get("/items")
async def read_items(user_agent: str | None = None):
    return {"User-Agent": user_agent}

この場合、FastAPI は

「ただの引数だな」

と判断するため、何も値を入れてくれません。

Header() があることで初めて、

「この値は HTTP ヘッダーから取得する」

というロジックが組み込まれます。


時系列で整理

サーバー起動時

  • @app.get() が関数を解析
  • Header() を発見
  • 「このエンドポイントではヘッダーを読む」という処理手順を登録

リクエスト時

  • FastAPI のラッパー関数が実行
  • ヘッダーを読み取る
  • 値を引数にセット
  • 関数を呼ぶ

処理のイメージ図

HTTPリクエスト
      ↓
FastAPIラッパー(ここでHeaderを読む)
      ↓
あなたの関数

なぜ Annotated を使うのか

以前は次のように書いていました。

user_agent: str | None = Header(default=None)

現在の推奨は:

user_agent: Annotated[str | None, Header()] = None

理由は、

「型」と「どこから取得するか」の情報を分離できるから

FastAPI がより正確に解析できるようになっています。


まとめ

Header() は魔法ではありません。

  • デコレーターではない
  • 関数の中でヘッダーを読んでいるわけでもない

FastAPI が、関数を実行する前にヘッダーを読む処理を自動で差し込んでいるだけです。

スポンサーリンク
Python
著者SNS
タイトルとURLをコピーしました