mirror of
http://88.130.71.182:3000/BlitTech/deals24togo_be.git
synced 2026-06-12 23:33:21 +00:00
96 lines
2.7 KiB
Python
96 lines
2.7 KiB
Python
"""FastAPI application factory."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
import sentry_sdk
|
|
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
from slowapi import Limiter, _rate_limit_exceeded_handler
|
|
from slowapi.errors import RateLimitExceeded
|
|
from slowapi.util import get_remote_address
|
|
|
|
from app.api.v1.router import api_router
|
|
from app.core.config import get_settings
|
|
from app.core.exceptions import AppException
|
|
from app.core.logging import get_logger, setup_logging
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""Startup / shutdown events."""
|
|
setup_logging()
|
|
settings = get_settings()
|
|
|
|
# Sentry
|
|
if settings.SENTRY_DSN:
|
|
sentry_sdk.init(
|
|
dsn=settings.SENTRY_DSN,
|
|
traces_sample_rate=0.1,
|
|
environment=settings.APP_ENV,
|
|
)
|
|
|
|
logger.info(
|
|
"application_started",
|
|
app_name=settings.APP_NAME,
|
|
env=settings.APP_ENV,
|
|
)
|
|
yield
|
|
logger.info("application_shutdown")
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
settings = get_settings()
|
|
|
|
app = FastAPI(
|
|
title=f"{settings.APP_NAME} API",
|
|
description="Marketplace API for Deals24Togo — listings, agencies, categories, and more.",
|
|
version="1.0.0",
|
|
docs_url="/docs" if settings.DEBUG else None,
|
|
redoc_url="/redoc" if settings.DEBUG else None,
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# ── CORS ──
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.allowed_origins_list,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# ── Rate limiter ──
|
|
limiter = Limiter(key_func=get_remote_address)
|
|
app.state.limiter = limiter
|
|
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
|
|
|
# ── Exception handlers ──
|
|
@app.exception_handler(AppException)
|
|
async def app_exception_handler(_request: Request, exc: AppException):
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content={"detail": exc.detail},
|
|
)
|
|
|
|
@app.exception_handler(Exception)
|
|
async def global_exception_handler(_request: Request, exc: Exception):
|
|
logger.error("unhandled_exception", error=str(exc), exc_info=True)
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={"detail": "Internal server error"},
|
|
)
|
|
|
|
# ── Routes ──
|
|
app.include_router(api_router)
|
|
|
|
@app.get("/health", tags=["Health"])
|
|
def health_check():
|
|
return {"status": "healthy", "app": settings.APP_NAME, "env": settings.APP_ENV}
|
|
|
|
return app
|