コンテンツにスキップ

クッキーパラメータモデル

もし関連する複数のクッキーから成るグループがあるなら、それらを宣言するために、Pydanticモデルを作成できます。🍪

こうすることで、複数の場所そのPydanticモデルを再利用でき、バリデーションやメタデータを、すべてのクッキーパラメータに対して一度に宣言できます。😎

備考

この機能は、FastAPIのバージョン 0.115.0 からサポートされています。🤓

豆知識

これと同じテクニックは QueryCookieHeader にも適用できます。 😎

クッキーにPydanticモデルを使用する

必要な複数のクッキーパラメータをPydanticモデルで宣言し、さらに、それを Cookie として宣言しましょう:

from typing import Annotated

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    session_id: str
    fatebook_tracker: str | None = None
    googall_tracker: str | None = None


@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
    return cookies
🤓 Other versions and variants
from typing import Annotated, Union

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    session_id: str
    fatebook_tracker: Union[str, None] = None
    googall_tracker: Union[str, None] = None


@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
    return cookies
from typing import Union

from fastapi import Cookie, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated

app = FastAPI()


class Cookies(BaseModel):
    session_id: str
    fatebook_tracker: Union[str, None] = None
    googall_tracker: Union[str, None] = None


@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
    return cookies

Tip

Prefer to use the Annotated version if possible.

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    session_id: str
    fatebook_tracker: str | None = None
    googall_tracker: str | None = None


@app.get("/items/")
async def read_items(cookies: Cookies = Cookie()):
    return cookies

Tip

Prefer to use the Annotated version if possible.

from typing import Union

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    session_id: str
    fatebook_tracker: Union[str, None] = None
    googall_tracker: Union[str, None] = None


@app.get("/items/")
async def read_items(cookies: Cookies = Cookie()):
    return cookies

FastAPIは、リクエストのクッキーからそれぞれのフィールドのデータを抽出し、定義されたPydanticモデルを提供します。

ドキュメントの確認

対話的APIドキュメントUI /docs で、定義されているクッキーを確認できます:

備考

ブラウザがクッキーを処理していますが、特別な方法で内部的に処理を行っているために、JavaScriptからは簡単に操作できないことに留意してください。

対話的APIドキュメントUI /docs にアクセスすれば、パスオペレーションに関するクッキーのドキュメンテーションを確認できます。

しかし、たとえクッキーデータを入力して「Execute」をクリックしても、対話的APIドキュメントUIはJavaScriptで動作しているためクッキーは送信されず、まるで値を入力しなかったかのようなエラーメッセージが表示されます。

余分なクッキーを禁止する

特定の(あまり一般的ではないかもしれない)ケースで、受け付けるクッキーを制限する必要があるかもしれません。

あなたのAPIは独自の クッキー同意 を管理する能力を持っています。 🤪🍪

Pydanticのモデルの Configuration を利用して、 extra フィールドを forbid とすることができます。

from typing import Annotated, Union

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    model_config = {"extra": "forbid"}

    session_id: str
    fatebook_tracker: Union[str, None] = None
    googall_tracker: Union[str, None] = None


@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
    return cookies
🤓 Other versions and variants
from typing import Annotated

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    model_config = {"extra": "forbid"}

    session_id: str
    fatebook_tracker: str | None = None
    googall_tracker: str | None = None


@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
    return cookies
from typing import Union

from fastapi import Cookie, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated

app = FastAPI()


class Cookies(BaseModel):
    model_config = {"extra": "forbid"}

    session_id: str
    fatebook_tracker: Union[str, None] = None
    googall_tracker: Union[str, None] = None


@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
    return cookies

Tip

Prefer to use the Annotated version if possible.

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    model_config = {"extra": "forbid"}

    session_id: str
    fatebook_tracker: str | None = None
    googall_tracker: str | None = None


@app.get("/items/")
async def read_items(cookies: Cookies = Cookie()):
    return cookies

Tip

Prefer to use the Annotated version if possible.

from typing import Union

from fastapi import Cookie, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Cookies(BaseModel):
    model_config = {"extra": "forbid"}

    session_id: str
    fatebook_tracker: Union[str, None] = None
    googall_tracker: Union[str, None] = None


@app.get("/items/")
async def read_items(cookies: Cookies = Cookie()):
    return cookies

もしクライアントが余分なクッキーを送ろうとすると、エラーレスポンスが返されます。

どうせAPIに拒否されるのにあなたの同意を得ようと精一杯努力する可哀想なクッキーバナーたち... 🍪

例えば、クライアントがクッキー santa_trackergood-list-please という値で送ろうとすると、santa_tracker という クッキーが許可されていない ことを通知するエラーレスポンスが返されます:

{
    "detail": [
        {
            "type": "extra_forbidden",
            "loc": ["cookie", "santa_tracker"],
            "msg": "Extra inputs are not permitted",
            "input": "good-list-please",
        }
    ]
}

まとめ

FastAPIでは、クッキーを宣言するために、Pydanticモデルを使用できます。😎