Ciclo de vida de la petición¶
El corazón HTTP de milpa es la fábrica create_app() en milpa/Core/Http/Http.py. Es el
equivalente al bootstrap de Laravel: arma la app de FastAPI, monta middlewares,
descubre los módulos y fija el ciclo de vida.
create_app()¶
Qué hace, en orden:
- Configura el logging (Loguru) — ver Logging.
- Crea la app:
FastAPI(title=settings.app_name, lifespan=_lifespan, dependencies=[Depends(_use_request_locale)]). - Registra los middlewares (
register_middlewares(app)). - Auto-monta los routers de los módulos (
iter_routers()). - Auto-monta los estáticos por módulo (
/static/<x>) y los compartidos (/static). - Expone un endpoint
/statusque devuelve{servicio, modulos, status}.
Es una app factory: uvicorn la llama con --factory, así cada arranque construye una
instancia fresca (necesario para --reload).
Lifespan (arranque y apagado)¶
- Antes del
yield(startup): importa todos los modelos y, solo siAUTO_CREATE_TABLES=true, crea las tablas. Loguea los módulos activos. - Después del
yield(shutdown): limpieza (vacío hoy).
Frontera de locale¶
async def _use_request_locale(accept_language: str = Header(default="")) -> None:
set_request_locale(resolve_accept_language(accept_language))
Esta dependency es global (dependencies=[Depends(_use_request_locale)] en
create_app), así que corre en todos los endpoints. Lee el header Accept-Language,
resuelve el idioma (es-MX → es, toma el de mayor q) y lo fija en un contextvar.
A partir de ahí, t() y current_locale() lo usan sin que tengas que pasarlo.
Es async a propósito: una dependency sync correría en un threadpool distinto y el
contextvar.set() no sería visible para el handler. Ver Localización.
Middlewares¶
milpa/Core/Http/Middleware.py → register_middlewares(app). Cada middleware se monta
solo si su setting lo activa (defaults seguros: nada de más):
| Middleware | Se monta si… | Settings |
|---|---|---|
| GZip | GZIP_ENABLED=true |
gzip_min_size |
| TrustedHost | TRUSTED_HOSTS ≠ * |
trusted_hosts (coma-separado) |
| CORS | CORS_ALLOW_ORIGINS no vacío |
cors_allow_* |
Orden: el último que se agrega es el más externo. CORS se agrega al final para que procese el preflight
OPTIONSantes que los demás. No cambies el orden sin saber esto.
Configúralos en el .env (ver Configuración). En producción:
restringe TRUSTED_HOSTS a tus dominios y CORS_ALLOW_ORIGINS a tus orígenes.
El endpoint /status¶
create_app() registra un único endpoint propio:
Útil para health checks y para confirmar qué módulos están montados. Todo lo demás viene de los módulos (ver Rutas y controladores).
Flujo completo de una petición¶
Request
→ middlewares (CORS / TrustedHost / GZip, los que estén activos)
→ dependency global _use_request_locale (fija el locale desde Accept-Language)
→ router del módulo (auto-montado por iter_routers)
→ tu handler
→ response