Files
HabitForge/backend/main.py
T
2026-07-30 23:25:20 -04:00

76 lines
2.7 KiB
Python

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from sqlalchemy.orm import Session
import os
from backend.core.config import settings
from backend.api.v1 import (
auth as auth_router,
challenges as challenges_router,
health as health_router,
# google as google_router,
health_connect as health_connect_router,
health_connect_raw as health_connect_raw_router,
health_analytics as health_analytics_router
)
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
# Rate limiting setup
limiter = Limiter(key_func=get_remote_address)
app = FastAPI(title=settings.APP_NAME, version=settings.APP_VERSION)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
# Create database tables on startup
@app.on_event("startup")
def on_startup():
from backend.database import Base, engine
import backend.models # This registers all models in the namespace for Base.metadata.create_all
Base.metadata.create_all(bind=engine)
# CORS - Use configured origins
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
allow_methods=settings.CORS_ALLOW_METHODS,
allow_headers=settings.CORS_ALLOW_HEADERS,
)
# Include API v1 routers
app.include_router(auth_router.router)
app.include_router(challenges_router.router)
app.include_router(health_router.router)
# app.include_router(google_router.router)
app.include_router(health_connect_router.router)
app.include_router(health_connect_raw_router.router)
app.include_router(health_analytics_router.router)
# Middleware to drop unexpected WebSocket connections (Fixes StaticFiles crash)
@app.middleware("http")
async def reject_websockets(request, call_next):
return await call_next(request)
from starlette.websockets import WebSocket
@app.websocket("/{path:path}")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
await websocket.close()
@app.get("/api/static/images")
def get_static_images():
"""Retrieve list of available static images."""
static_dir = os.path.join("frontend", "static")
images = []
if os.path.exists(static_dir):
for filename in os.listdir(static_dir):
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')):
images.append(filename)
return images
# Mount static files last to avoid intercepting API calls
app.mount("/", StaticFiles(directory="frontend", html=True), name="frontend")