FastAPI na prática: routers, DI e auth
⏱ 14 min·⭐ 60 XP
Pré-requisitos (0/1)0%
- ⬜⏳ Async em Python: asyncio, trio e trade-offs vs Node(Python para Engenheiros)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Router + DI
🗺️ O caminho de uma requisição, e onde cada garantia entra
1 · Roteamentocaminho e método
A assinatura da função é o contrato — dela saem a validação e a documentação publicada.
VALIDA▼
2 · Validação do corpomodelo de entrada
Requisição malformada é recusada aqui, com mensagem que aponta o campo. Sua função só roda com dado válido.
DEPENDE▼
3 · Injeção de dependênciasbanco, sessão, permissão
É este ponto que o teste substitui — sem tocar na rota, que permanece idêntica à de produção.
EXECUTA▼
4 · Sua lógicaa única parte específica
Recebe tipos já garantidos e devolve um objeto; a serialização não é problema seu.
SERIALIZA▼
5 · Modelo de saídacontrato de resposta
Também filtra: campo que não está no modelo de saída não vaza, mesmo que o objeto interno o tenha.
from fastapi import FastAPI, APIRouter, Depends, HTTPException
from pydantic import BaseModel
app = FastAPI(title="Tasks API", version="1.0.0")
class TaskIn(BaseModel):
title: str
description: str | None = None
class TaskOut(TaskIn):
id: str
# Router (module)
tasks = APIRouter(prefix="/tasks", tags=["tasks"])
async def get_db():
# scope: request — FastAPI abre conexão, fecha no fim
async with AsyncSession() as session:
yield session
@tasks.post("", response_model=TaskOut, status_code=201)
async def create_task(body: TaskIn, db=Depends(get_db)) -> TaskOut:
task = await db.tasks.insert(body.model_dump())
return task
@tasks.get("/{id}", response_model=TaskOut)
async def get_task(id: str, db=Depends(get_db)) -> TaskOut:
task = await db.tasks.find(id)
if not task: raise HTTPException(404, "not found")
return task
app.include_router(tasks)Auth com JWT
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import jwt, JWTError
bearer = HTTPBearer()
class TokenPayload(BaseModel):
sub: str
exp: int
async def current_user(cred: HTTPAuthorizationCredentials = Depends(bearer)) -> TokenPayload:
try:
payload = jwt.decode(cred.credentials, SECRET, algorithms=["HS256"])
return TokenPayload(**payload)
except JWTError:
raise HTTPException(401, "invalid token")
@tasks.get("/me")
async def my_tasks(user: TokenPayload = Depends(current_user), db=Depends(get_db)):
return await db.tasks.find_by_user(user.sub)Testes
import pytest
from httpx import AsyncClient, ASGITransport
from app.main import app, get_db
@pytest.fixture
def client():
# Override de dep
app.dependency_overrides[get_db] = lambda: MockDb()
return AsyncClient(transport=ASGITransport(app=app), base_url="http://test")
@pytest.mark.asyncio
async def test_create_task(client: AsyncClient):
r = await client.post("/tasks", json={"title": "buy milk"})
assert r.status_code == 201
assert r.json()["title"] == "buy milk"Quiz rápido
Nos testes, o acesso ao banco é trocado sobrescrevendo a dependência. Por que esse ponto de injeção importa mais do que parece?
OpenAPI grátis
FastAPI gera /docs (Swagger UI) e /redoc automaticamente a partir dos tipos. Schemas Pydantic viram schemas OpenAPI, deps viram parameters, response_model vira schema de resposta. Docs sempre atualizadas — zero manutenção.
✅
Padrão de time FastAPI sério: Settings (pydantic-settings) + Router por domínio + Depends pra auth/db + pytest-asyncio + ruff + mypy strict. Stack completa que escala.
Perguntas frequentes
❓ Por que esse arcabouço virou padrão?
Porque ele usa a anotação de tipo para validar entrada, gerar documentação e injetar dependência — três coisas que antes eram manuais. O tipo deixa de ser documentação e passa a ter efeito, o que é a mesma ideia que faz TypeScript valer a pena.
❓ Como organizar rotas em projeto grande?
Por roteadores separados por domínio, com dependências declaradas no nível do roteador — autenticação, sessão de banco, permissão. Concentrar tudo num arquivo funciona até algumas dezenas de rotas e depois se torna o gargalo de revisão.
❓ Como fazer autenticação sem reinventar?
Com dependência que resolve o usuário a partir do token e é declarada nas rotas protegidas, mais verificação de permissão sobre o RECURSO dentro do manipulador. A dependência cuida de quem é; a autorização por recurso é a parte que o arcabouço não faz por você.
Fixando
Quiz rápido
A documentação OpenAPI sai de graça no FastAPI. De onde ela vem, exatamente?
Quiz rápido
Qual é o efeito de tipar o payload do token com um modelo em vez de usar o dicionário decodificado direto?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…