mirror of
http://88.130.71.182:3000/BlitTech/deals24togo_be.git
synced 2026-06-12 23:33:21 +00:00
Initial commit
This commit is contained in:
95
app/main.py
Normal file
95
app/main.py
Normal file
@@ -0,0 +1,95 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user