Concepto clave
La arquitectura de FastAPI se basa en el patrón ASGI (Asynchronous Server Gateway Interface), que permite manejar múltiples solicitudes concurrentes de manera eficiente. Piensa en ASGI como un sistema de gestión de tráfico en una ciudad inteligente: en lugar de tener un solo semáforo que detiene todo el flujo (como en WSGI), ASGI coordina múltiples intersecciones simultáneamente, permitiendo que el tráfico (solicitudes HTTP) fluya sin bloqueos.
La configuración avanzada implica entender cómo FastAPI organiza las dependencias, middleware y routers. Imagina construir un edificio modular: cada módulo (router) tiene su propia estructura, pero todos comparten cimientos comunes (dependencias) y sistemas de seguridad (middleware). La clave está en mantener un equilibrio entre modularidad y coherencia, evitando duplicaciones y asegurando que cada componente sea testeable y mantenible.
Cómo funciona en la práctica
Vamos a implementar una arquitectura escalable paso a paso. Primero, estructuramos el proyecto separando routers, dependencias y modelos en módulos independientes. Luego, configuramos middleware para logging y seguridad, y finalmente optimizamos las dependencias para reutilización.
Paso 1: Crear la estructura de directorios:
# Estructura recomendada para proyectos avanzados
proyecto/
├── app/
│ ├── __init__.py
│ ├── main.py # Punto de entrada
│ ├── api/
│ │ ├── __init__.py
│ │ ├── v1/
│ │ │ ├── __init__.py
│ │ │ ├── endpoints/
│ │ │ │ ├── users.py
│ │ │ │ └── products.py
│ │ │ └── routers.py # Agrupa routers
│ ├── core/
│ │ ├── config.py # Configuración
│ │ └── security.py # Autenticación
│ ├── models/
│ │ └── schemas.py # Pydantic models
│ └── dependencies.py # Dependencias compartidas
Paso 2: Configurar el archivo main.py para cargar routers y middleware de manera modular.
Codigo en accion
Antes: Una aplicación monolítica con todo en un solo archivo, difícil de escalar.
# main_antes.py - Ejemplo NO recomendado
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get("/items/")
async def read_items():
return [{"name": "item1", "price": 10.0}]
@app.post("/items/")
async def create_item(item: Item):
return item
# Más endpoints aquí...
Después: Arquitectura modular con separación de responsabilidades.
# app/main.py - Punto de entrada optimizado
from fastapi import FastAPI
from app.api.v1.routers import api_router
from app.core.middleware import add_middleware
app = FastAPI(title="API Escalable", version="1.0.0")
# Agregar middleware personalizado
add_middleware(app)
# Incluir routers agrupados
app.include_router(api_router, prefix="/api/v1")
# app/api/v1/routers.py
from fastapi import APIRouter
from app.api.v1.endpoints import users, products
api_router = APIRouter()
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(products.router, prefix="/products", tags=["products"])
# app/api/v1/endpoints/users.py
from fastapi import APIRouter, Depends
from app.models.schemas import UserCreate, UserResponse
from app.dependencies import get_db
router = APIRouter()
@router.post("/", response_model=UserResponse)
async def create_user(user: UserCreate, db=Depends(get_db)):
# Lógica de negocio aquí
return {"id": 1, "name": user.name}
Errores comunes
- Acoplamiento excesivo: Crear dependencias directas entre módulos, haciendo el código difícil de testear. Solución: Usar inyección de dependencias con
Depends()para desacoplar. - Middleware mal configurado: Agregar middleware en orden incorrecto, afectando seguridad o performance. Solución: Ordenar middleware según prioridad (ej: CORS antes de autenticación).
- Duplicación de lógica: Repetir validaciones o queries en múltiples endpoints. Solución: Centralizar en dependencias reutilizables.
- Ignorar ASGI: No aprovechar capacidades asíncronas, bloqueando el servidor. Solución: Usar
async/awaiten operaciones I/O. - Configuración hardcodeada: Embeber valores como URLs de BD en el código. Solución: Usar variables de entorno con
pydantic-settings.
Checklist de dominio
- ¿Estructuré el proyecto en módulos independientes (routers, modelos, dependencias)?
- ¿Configuré middleware para logging, CORS y seguridad de manera óptima?
- ¿Implementé dependencias reutilizables para autenticación y acceso a BD?
- ¿Utilicé
APIRouterpara agrupar endpoints relacionados? - ¿Validé que todas las operaciones I/O sean asíncronas?
- ¿Centralicé la configuración en variables de entorno?
- ¿Documenté la arquitectura con docstrings y tipos de datos?
Refactorización de una API Monolítica a Arquitectura Modular
Refactoriza la siguiente API FastAPI monolítica en una arquitectura modular escalable. Sigue estos pasos:
- Crea la estructura de directorios recomendada (app/, api/, core/, models/).
- Separa los endpoints en routers independientes para usuarios y productos.
- Implementa una dependencia reutilizable para simular acceso a base de datos.
- Agrega middleware básico para logging de solicitudes.
- Configura la aplicación principal para incluir routers y middleware.
Código inicial (monolítico):
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
name: str
email: str
class Product(BaseModel):
name: str
price: float
@app.get("/users/")
async def get_users():
return [{"name": "Alice", "email": "[email protected]"}]
@app.post("/users/")
async def create_user(user: User):
return {"id": 1, **user.dict()}
@app.get("/products/")
async def get_products():
return [{"name": "Laptop", "price": 999.99}]
@app.post("/products/")
async def create_product(product: Product):
return {"id": 1, **product.dict()}
Entrega la estructura final con al menos 5 archivos Python funcionales.
Pistas- Usa APIRouter para cada conjunto de endpoints (usuarios, productos).
- Crea un archivo dependencies.py con una función que simule una conexión a BD.
- En main.py, importa y include los routers con prefijos apropiados.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.