Ir para o conteúdo

Modelos de Parâmetros de Cookie

Se você possui um grupo de cookies que estão relacionados, você pode criar um modelo Pydantic para declará-los. 🍪

Isso lhe permitiria reutilizar o modelo em diversos lugares e também declarar validações e metadata para todos os parâmetros de uma vez. 😎

Nota

Isso é suportado desde a versão 0.115.0 do FastAPI. 🤓

Dica

Essa mesma técnica se aplica para Query, Cookie, e Header. 😎

Cookies com Modelos Pydantic

Declare o parâmetro de cookie que você precisa em um modelo Pydantic, e depois declare o parâmetro como um 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
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

Dica

Prefira utilizar a versão Annotated se possível.

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

Dica

Prefira utilizar a versão Annotated se possível.

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

O FastAPI irá extrair os dados para cada campo dos cookies recebidos na requisição e lhe fornecer o modelo Pydantic que você definiu.

Verifique os Documentos

Você pode ver os cookies definidos na IU dos documentos em /docs:

Informação

Tenha em mente que, como os navegadores lidam com cookies de maneira especial e por baixo dos panos, eles não permitem facilmente que o JavaScript lidem com eles.

Se você for na IU de documentos da API em /docs você poderá ver a documentação para cookies das suas operações de rotas.

Mas mesmo que você adicionar os dados e clicar em "Executar", pelo motivo da IU dos documentos trabalharem com JavaScript, os cookies não serão enviados, e você verá uma mensagem de erro como se você não tivesse escrito nenhum dado.

Proibir Cookies Adicionais

Em alguns casos especiais (provavelmente não muito comuns), você pode querer restringir os cookies que você deseja receber.

Agora a sua API possui o poder de contrar o seu próprio consentimento de cookie. 🤪🍪

Você pode utilizar a configuração do modelo Pydantic para proibir qualquer campo extra.

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
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

Dica

Prefira utilizar a versão Annotated se possível.

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

Se o cliente tentar enviar alguns cookies extras, eles receberão um retorno de erro.

Coitados dos banners de cookies com todo o seu esforço para obter o seu consentimento para a API rejeitá-lo. 🍪

Por exemplo, se o cliente tentar enviar um cookie santa_tracker com o valor de good-list-please, o cliente receberá uma resposta de erro informando que o cookie santa_tracker is not allowed:

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

Resumo

Você consegue utilizar modelos Pydantic para declarar cookies no FastAPI. 😎