Add the experience service with sites through analytics/AI hooks, migrations through 0011, and phase docs/manifests marking the track complete. Co-authored-by: Cursor <cursoragent@cursor.com>
70 lines
2.3 KiB
Python
70 lines
2.3 KiB
Python
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from app import __version__
|
|
from app.api.v1 import api_router
|
|
from app.api.v1 import health
|
|
from app.core.config import settings
|
|
from app.core.logging import configure_logging, get_logger
|
|
from app.middlewares.tenant import TenantHeaderMiddleware
|
|
from shared.exceptions import AppError
|
|
from shared.responses import ErrorDetail, ErrorResponse
|
|
|
|
configure_logging(settings.log_level)
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
logger.info("service_starting", extra={"service": settings.service_name})
|
|
yield
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
app = FastAPI(
|
|
title="Experience Platform",
|
|
version=__version__,
|
|
description="Torbat Pages — Experience Platform (Phase 11.9 Consumer Integrations & Widgets)",
|
|
lifespan=lifespan,
|
|
)
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origin_list,
|
|
allow_origin_regex=r"https?://([a-z0-9-]+\.)*torbatyar\.ir",
|
|
allow_credentials=False,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
app.add_middleware(TenantHeaderMiddleware)
|
|
|
|
@app.exception_handler(AppError)
|
|
async def app_error_handler(request: Request, exc: AppError) -> JSONResponse:
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=ErrorResponse(
|
|
error=ErrorDetail(
|
|
code=exc.error_code, message=exc.message, details=exc.details
|
|
)
|
|
).model_dump(),
|
|
)
|
|
|
|
@app.exception_handler(Exception)
|
|
async def unhandled_handler(request: Request, exc: Exception) -> JSONResponse:
|
|
logger.error("unhandled_exception", extra={"error": str(exc)}, exc_info=exc)
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content=ErrorResponse(
|
|
error=ErrorDetail(code="internal_error", message="خطای داخلی سرور")
|
|
).model_dump(),
|
|
)
|
|
|
|
app.include_router(health.router)
|
|
app.include_router(api_router, prefix=settings.api_v1_prefix)
|
|
return app
|
|
|
|
|
|
app = create_app()
|