Files
Mireya Cueto Garrido 7dcc7dc0e1 Align Sinbad2 HTTPS deployment with orcid2sword reverse-proxy pattern.
This adds nginx dual-path routing, forwarded proxy headers, Uvicorn proxy-headers, production security settings, and deployment docs for https://sinbad2.ujaen.es/generadorexamenesllm/.
2026-06-03 10:12:05 +02:00

58 lines
2.2 KiB
Python

from contextlib import asynccontextmanager
from collections.abc import AsyncIterator
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from starlette.middleware.trustedhost import TrustedHostMiddleware
from app.api.routes import auth, exports, generation, health, history, images, materials, questions, templates
from app.core.config import get_settings
from app.core.errors import register_exception_handlers
from app.core.middleware import RateLimitMiddleware, RequestSizeLimitMiddleware
from app.core.security_headers import SecurityHeadersMiddleware
from app.db.init_db import init_db
@asynccontextmanager
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
init_db()
yield
def create_app() -> FastAPI:
settings = get_settings()
app = FastAPI(title=settings.app_name, lifespan=lifespan)
# CORS debe ser el middleware más externo (añadirlo al final) para que
# las peticiones OPTIONS (preflight) respondan antes que rate limit, etc.
app.add_middleware(RequestSizeLimitMiddleware, settings=settings)
app.add_middleware(RateLimitMiddleware, settings=settings)
app.add_middleware(SecurityHeadersMiddleware, settings=settings)
if settings.trusted_hosts_list:
app.add_middleware(TrustedHostMiddleware, allowed_hosts=settings.trusted_hosts_list)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_credentials=True,
allow_methods=["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
allow_headers=["Authorization", "Content-Type", "X-API-Key", "Accept"],
expose_headers=["Content-Disposition"],
)
register_exception_handlers(app)
app.include_router(health.router)
app.include_router(auth.router)
app.include_router(templates.router, prefix="/exam")
app.include_router(generation.router, prefix="/exam")
app.include_router(exports.router, prefix="/exam")
app.include_router(history.router, prefix="/exam")
app.include_router(materials.router, prefix="/exam")
app.include_router(images.router, prefix="/exam")
app.include_router(questions.router, prefix="/exam")
return app
app = create_app()