Neda/Back/main.py
2026-03-29 16:40:30 +03:30

84 lines
2.6 KiB
Python

from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi_swagger import patch_fastapi
from domains.auth.api import router as auth_router
from domains.users.api import router as users_router
from domains.admin.api import router as admin_router
from domains.groups.api.admin import router as groups_admin_router
from domains.groups.api.client import router as groups_client_router
from domains.realtime.ws import router as realtime_router
from domains.notifications.api import router as notifications_router
from integrations.livekit.client import close_livekit_api
from db.redis import redis_client
from core.rate_limit import RateLimiter
@asynccontextmanager
async def lifespan(app: FastAPI):
# ---------- Startup ----------
try:
await redis_client.ping() # type: ignore
print("Redis connected")
async for key in redis_client.scan_iter("speaker:*"):
await redis_client.delete(key)
async for key in redis_client.scan_iter("presence:*"):
await redis_client.delete(key)
except Exception as e:
print("Redis connection failed:", e)
yield
# ---------- Shutdown ----------
await close_livekit_api()
await redis_client.close()
global_limiter = RateLimiter(requests=30, window_seconds=60, scope="global")
app = FastAPI(
title="NEDA API",
description="Realtime Voice Communication Backend",
version="1.0.0",
lifespan=lifespan,
docs_url=None,
swagger_ui_oauth2_redirect_url=None,
dependencies=[Depends(global_limiter)]
)
patch_fastapi(app,docs_url="/swagger")
# -------------------------
# CORS
# -------------------------
app.add_middleware(
CORSMiddleware,
allow_origins=[
"https://pathfinder.wikm.ir",
"http://localhost:8000",
],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "*"], # محدود کردن متدها
allow_headers=["Authorization", "Content-Type"], # محدود کردن هدرها
)
@app.middleware("http")
async def add_security_headers(request: Request, call_next):
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
return response
# -------------------------
# Routers
# -------------------------
app.include_router(auth_router)
app.include_router(users_router)
app.include_router(admin_router)
app.include_router(groups_client_router)
app.include_router(groups_admin_router)
app.include_router(realtime_router)
app.include_router(notifications_router)