ARCHIVISE / app /main.py
UNI12345's picture
fix: add fallback defaults to Settings and fix limiter import in auth router
ed654df
Raw
History Blame Contribute Delete
3.13 kB
import sentry_sdk
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from slowapi import _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from app.config import settings
from app.limiter import limiter, get_real_client_ip
from app.routers import auth, audit, design, github, billing, settings as settings_router, legal, projects
from loguru import logger
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info(f"{settings.APP_NAME} API startup complete. Environment: {'DEBUG' if settings.DEBUG else 'PRODUCTION'}")
yield
logger.info(f"{settings.APP_NAME} shutting down.")
app = FastAPI(
title=settings.APP_NAME,
description="Archvise SaaS Backend Engine",
version=settings.API_VERSION,
debug=settings.DEBUG,
lifespan=lifespan
)
# Attach Limiter to App State
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
# Configure CORS Middleware
# Build list of allowed origins from config and defaults
allowed_origins = [
"http://localhost:3000",
"https://archvise.vercel.app",
]
if isinstance(settings.CORS_ORIGINS, list):
allowed_origins.extend(settings.CORS_ORIGINS)
elif isinstance(settings.CORS_ORIGINS, str) and settings.CORS_ORIGINS != "*":
allowed_origins.append(settings.CORS_ORIGINS)
app.add_middleware(
CORSMiddleware,
allow_origins=list(set(allowed_origins)),
allow_origin_regex=r"https://archvise-.*\.vercel\.app",
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Register Routers
app.include_router(auth.router, prefix="/api")
app.include_router(audit.router, prefix="/api")
app.include_router(design.router, prefix="/api")
app.include_router(github.router, prefix="/api")
app.include_router(billing.router, prefix="/api")
app.include_router(settings_router.router, prefix="/api")
app.include_router(legal.router, prefix="/api")
app.include_router(projects.router, prefix="/api")
@app.get("/")
def read_root():
return {"status": "online", "app": settings.APP_NAME, "version": settings.API_VERSION}
@app.get("/health")
async def health_check():
"""Liveness + readiness probe — checks DB and Redis connectivity."""
import redis as redis_lib
from app.database import engine
from sqlalchemy import text
checks = {"database": "ok", "redis": "ok"}
status_code = 200
# Check DB
try:
async with engine.connect() as conn:
await conn.execute(text("SELECT 1"))
except Exception as e:
checks["database"] = f"error: {str(e)[:80]}"
status_code = 503
# Check Redis
try:
r = redis_lib.Redis.from_url(settings.REDIS_URL, socket_connect_timeout=2)
r.ping()
r.close()
except Exception as e:
checks["redis"] = f"error: {str(e)[:80]}"
status_code = 503
from fastapi.responses import JSONResponse
return JSONResponse(content={"status": "healthy" if status_code == 200 else "degraded", **checks}, status_code=status_code)