Introdução ao desenvolvimento de APIs com FastAPI
1. O que é FastAPI e por que ele se destaca?
FastAPI é um framework moderno e rápido para construção de APIs com Python 3.7+, lançado em 2018 por Sebastián Ramírez. Sua principal característica é a alta performance — comparável a frameworks assíncronos como Node.js e Go — combinada com tipagem estática e validação automática de dados.
Características principais:
- Alta performance: utiliza Starlette (framework ASGI) como base, com suporte nativo a async/await
- Tipagem com Pydantic: modelos Pydantic validam automaticamente tipos, valores obrigatórios e formatos
- Documentação automática: gera interfaces Swagger (/docs) e ReDoc (/redoc) sem configuração
- Injeção de dependências: sistema elegante para reutilizar lógica (autenticação, banco, etc.)
Comparação rápida:
| Framework | Performance | Documentação automática | Validação | Curva de aprendizado |
|-----------|-------------|------------------------|-----------|----------------------|
| FastAPI | Muito alta | Sim | Nativa (Pydantic) | Média |
| Flask | Média | Não | Manual | Baixa |
| Django | Média | Parcial | Parcial (DRF) | Alta |
Casos de uso ideais: microsserviços, prototipagem rápida de MVPs, APIs com validação rigorosa de dados, sistemas que exigem alta concorrência e documentação viva.
2. Configuração do ambiente e primeiro projeto
Crie um ambiente virtual e instale as dependências:
python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
pip install fastapi uvicorn
Estrutura básica de diretórios para o projeto:
meu_projeto/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ ├── routes.py
│ └── database.py
├── tests/
│ └── test_main.py
└── requirements.txt
Crie o arquivo app/main.py com o "Hello World" assíncrono:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
Execute com Uvicorn:
uvicorn app.main:app --reload
Acesse http://127.0.0.1:8000 e veja a resposta JSON. O --reload permite recarregamento automático durante o desenvolvimento.
3. Rotas, parâmetros e validação com Pydantic
Vamos expandir o main.py com diferentes tipos de rotas e parâmetros:
from fastapi import FastAPI, Path, Query
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
# Modelo Pydantic para validação
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
# GET com parâmetro de caminho
@app.get("/items/{item_id}")
async def read_item(item_id: int = Path(..., title="ID do item", ge=1)):
return {"item_id": item_id}
# GET com parâmetros de query
@app.get("/items/")
async def list_items(skip: int = Query(0, ge=0), limit: int = Query(10, ge=1, le=100)):
return {"skip": skip, "limit": limit}
# POST com corpo validado
@app.post("/items/")
async def create_item(item: Item):
return {"item": item.dict(), "price_with_tax": item.price * 1.1}
# PUT para atualização
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
return {"item_id": item_id, "item": item.dict()}
# DELETE
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
return {"message": f"Item {item_id} deleted"}
O Pydantic valida automaticamente: tipos (int, float, str), valores obrigatórios, valores opcionais e restrições como ge (greater or equal). Se os dados forem inválidos, o FastAPI retorna erro 422 com detalhes.
4. Documentação interativa automática (Swagger e ReDoc)
Sem qualquer configuração extra, acesse:
http://127.0.0.1:8000/docs— interface Swagger UIhttp://127.0.0.1:8000/redoc— interface ReDoc
Ambas exibem todas as rotas, parâmetros, modelos de dados e permitem testar as requisições diretamente.
Para personalizar a documentação, configure o FastAPI:
app = FastAPI(
title="Minha API de Exemplo",
description="API para demonstração do FastAPI",
version="1.0.0",
contact={
"name": "Seu Nome",
"url": "https://seusite.com",
"email": "email@exemplo.com",
},
license_info={
"name": "MIT",
"url": "https://opensource.org/licenses/MIT",
}
)
# Agrupe rotas com tags
@app.get("/users/", tags=["Usuários"])
async def get_users():
return [{"username": "joao"}, {"username": "maria"}]
@app.post("/items/", tags=["Itens"])
async def create_item(item: Item):
return item
5. Tratamento de erros e respostas padronizadas
Crie respostas consistentes com modelos unificados:
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from typing import Any, Optional
app = FastAPI()
# Modelos de resposta padronizados
class SuccessResponse(BaseModel):
success: bool = True
data: Any = None
message: str = "Operação realizada com sucesso"
class ErrorResponse(BaseModel):
success: bool = False
error_code: int
message: str
details: Optional[dict] = None
# Exceção personalizada
class NotFoundException(Exception):
def __init__(self, entity: str, entity_id: int):
self.entity = entity
self.entity_id = entity_id
@app.exception_handler(NotFoundException)
async def not_found_handler(request: Request, exc: NotFoundException):
return JSONResponse(
status_code=404,
content=ErrorResponse(
error_code=404,
message=f"{exc.entity} com ID {exc.entity_id} não encontrado"
).dict()
)
# Middleware global para logging
@app.middleware("http")
async def log_requests(request: Request, call_next):
print(f"Requisição: {request.method} {request.url}")
response = await call_next(request)
print(f"Resposta: {response.status_code}")
return response
# Rota com tratamento de erro
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id > 100:
raise NotFoundException(entity="Item", entity_id=item_id)
return SuccessResponse(data={"item_id": item_id, "name": "Exemplo"})
O HTTPException do FastAPI também pode ser usado diretamente:
from fastapi import HTTPException
@app.get("/secure-data/")
async def secure_data(api_key: str = Query(...)):
if api_key != "secret123":
raise HTTPException(
status_code=401,
detail="API key inválida",
headers={"X-Error": "Invalid API Key"}
)
return {"data": "informação secreta"}
6. Dependências e injeção de dependências
O sistema de dependências permite reutilizar lógica de forma limpa:
from fastapi import FastAPI, Depends, HTTPException, Header
from typing import Optional
app = FastAPI()
# Dependência simples: validação de token
async def verify_token(authorization: Optional[str] = Header(None)):
if authorization is None:
raise HTTPException(status_code=401, detail="Token não fornecido")
# Simulação de validação
if authorization != "Bearer token_valido":
raise HTTPException(status_code=403, detail="Token inválido")
return {"user": "admin", "token": authorization}
# Dependência para conexão com banco (simulada)
async def get_database():
db = {"connection": "simulada", "status": "conectado"}
try:
yield db # yield permite cleanup após uso
finally:
print("Conexão fechada")
# Rota protegida usando dependências
@app.get("/users/me")
async def get_current_user(
token_data: dict = Depends(verify_token),
db: dict = Depends(get_database)
):
return {
"user": token_data["user"],
"database_status": db["status"]
}
# Dependência com classe
class CommonQueryParams:
def __init__(self, skip: int = 0, limit: int = 100):
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends()):
return {"skip": commons.skip, "limit": commons.limit}
7. Testes automatizados com FastAPI e pytest
Instale o pytest e o httpx (usado pelo TestClient):
pip install pytest httpx
Crie tests/test_main.py:
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Hello World"}
def test_create_item():
response = client.post(
"/items/",
json={"name": "Notebook", "price": 2500.0}
)
assert response.status_code == 200
data = response.json()
assert data["item"]["name"] == "Notebook"
assert data["price_with_tax"] == 2750.0
def test_create_item_invalid():
response = client.post(
"/items/",
json={"name": "Teste"} # Faltando price
)
assert response.status_code == 422 # Erro de validação
def test_item_not_found():
response = client.get("/items/999")
assert response.status_code == 404
assert response.json()["error_code"] == 404
def test_authentication():
response = client.get("/users/me")
assert response.status_code == 401 # Sem token
response = client.get(
"/users/me",
headers={"Authorization": "Bearer token_valido"}
)
assert response.status_code == 200
# Teste com dependência mockada
def test_with_mock(mocker):
# Exemplo com pytest-mock
mock_db = {"connection": "mock", "status": "teste"}
mocker.patch("app.main.get_database", return_value=mock_db)
response = client.get(
"/users/me",
headers={"Authorization": "Bearer token_valido"}
)
assert response.status_code == 200
Execute os testes:
pytest tests/ -v
8. Deploy e boas práticas finais
Execução em produção com Gunicorn + Uvicorn:
pip install gunicorn
gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
Variáveis de ambiente (arquivo .env):
DATABASE_URL=postgresql://user:pass@localhost/db
SECRET_KEY=minha_chave_secreta
ENVIRONMENT=production
Carregue com python-dotenv ou pydantic-settings.
Checklist básico para produção:
- [ ] CORS: Configurar CORSMiddleware para origens permitidas
- [ ] Versionamento: Prefixo /v1/ nas rotas
- [ ] Segurança mínima: HTTPS, rate limiting, validação de entrada
- [ ] Logging: Estruturar logs com níveis (info, warning, error)
- [ ] Health check: Rota /health para monitoramento
- [ ] Documentação: Desabilitar /docs em produção ou proteger com autenticação
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://meudominio.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
async def health_check():
return {"status": "healthy", "version": "1.0.0"}
FastAPI oferece performance excepcional, documentação viva e um ecossistema maduro para construção de APIs modernas. Com os conceitos apresentados — rotas, validação, dependências, testes e deploy — você está pronto para desenvolver APIs robustas e escaláveis.
Referências
- FastAPI Official Documentation — Documentação oficial completa com tutoriais, guias e referência da API
- Pydantic Documentation — Documentação oficial do Pydantic, biblioteca de validação de dados usada pelo FastAPI
- Uvicorn Documentation — Documentação do servidor ASGI Uvicorn, recomendado para executar FastAPI em produção
- Real Python: FastAPI Tutorial — Tutorial abrangente sobre construção de APIs com FastAPI, incluindo banco de dados e testes
- TestDriven.io: FastAPI + PostgreSQL — Guia prático de integração do FastAPI com PostgreSQL, incluindo migrações e deploy
- FastAPI Best Practices — Repositório GitHub com boas práticas e padrões de projeto para FastAPI