Push the rest
This commit is contained in:
100
backend/app/main.py
Normal file
100
backend/app/main.py
Normal file
@@ -0,0 +1,100 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
import httpx
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.requests import Request as StarletteRequest
|
||||
from starlette.responses import Response as StarletteResponse
|
||||
|
||||
from app.core.audit import SharedBase
|
||||
from app.core.config import settings
|
||||
from app.core.db import create_postgres_engine, create_session_factory
|
||||
from app.core.executor import get_executor, shutdown_executor
|
||||
from app.core.otel import configure_otel, instrument_fastapi, instrument_sqlalchemy, shutdown_otel
|
||||
from app.domain.aw.models import AWBase
|
||||
from app.domain.wwi.models import WWIBase
|
||||
from app.routers import aw, platform, wwi
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request: StarletteRequest, call_next) -> StarletteResponse:
|
||||
response = await call_next(request)
|
||||
response.headers["X-Content-Type-Options"] = "nosniff"
|
||||
response.headers["X-Frame-Options"] = "DENY"
|
||||
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
|
||||
return response
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# --- startup ---
|
||||
providers = configure_otel(settings)
|
||||
LOGGER.info("OTel configured for %s", settings.otel_service_name)
|
||||
|
||||
pg_engine = create_postgres_engine()
|
||||
instrument_sqlalchemy({"pg": pg_engine})
|
||||
|
||||
SharedBase.metadata.create_all(pg_engine)
|
||||
AWBase.metadata.create_all(pg_engine)
|
||||
WWIBase.metadata.create_all(pg_engine)
|
||||
|
||||
pg_factory = create_session_factory(pg_engine)
|
||||
|
||||
analytics_client = httpx.AsyncClient(
|
||||
base_url=settings.analytics_service_url,
|
||||
timeout=httpx.Timeout(60.0),
|
||||
)
|
||||
|
||||
executor = get_executor()
|
||||
|
||||
app.state.pg_engine = pg_engine
|
||||
app.state.pg_factory = pg_factory
|
||||
app.state.analytics_client = analytics_client
|
||||
|
||||
LOGGER.info("Ready: analytics_service=%s thread_pool_workers=%d",
|
||||
settings.analytics_service_url, executor._max_workers) # noqa: SLF001
|
||||
|
||||
instrument_fastapi(app)
|
||||
|
||||
yield
|
||||
|
||||
# --- shutdown ---
|
||||
LOGGER.info("Shutting down")
|
||||
await analytics_client.aclose()
|
||||
shutdown_executor()
|
||||
pg_engine.dispose()
|
||||
shutdown_otel(providers)
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
app = FastAPI(
|
||||
title="otel-bi-backend",
|
||||
version="1.0.0",
|
||||
lifespan=lifespan,
|
||||
docs_url="/docs" if settings.app_env != "prod" else None,
|
||||
redoc_url=None,
|
||||
)
|
||||
|
||||
app.add_middleware(SecurityHeadersMiddleware)
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=settings.cors_origins_list,
|
||||
allow_credentials=True,
|
||||
allow_methods=["GET", "POST", "DELETE"],
|
||||
allow_headers=["Authorization", "Content-Type"],
|
||||
)
|
||||
|
||||
app.include_router(platform.router)
|
||||
app.include_router(aw.router)
|
||||
app.include_router(wwi.router)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
app = create_app()
|
||||
Reference in New Issue
Block a user