Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, Request, status | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from app.core.config import settings | |
| from app.api.router import api_router | |
| from app.core.database import Base, engine | |
| import logging | |
| # Set up logging | |
| logging.basicConfig(level=logging.INFO) | |
| # Initialize database tables | |
| try: | |
| Base.metadata.create_all(bind=engine) | |
| logging.info("Database tables initialized successfully.") | |
| # Proactively ensure chest_cm, waist_cm, hips_cm columns exist in body_profiles | |
| from sqlalchemy import text | |
| with engine.begin() as conn: | |
| for col in ["chest_cm", "waist_cm", "hips_cm"]: | |
| try: | |
| conn.execute(text(f"ALTER TABLE body_profiles ADD COLUMN IF NOT EXISTS {col} REAL;")) | |
| except Exception as e: | |
| # Fallback for SQLite or older databases where IF NOT EXISTS might fail | |
| try: | |
| conn.execute(text(f"ALTER TABLE body_profiles ADD COLUMN {col} REAL;")) | |
| except Exception: | |
| pass | |
| # Ensure chat_messages has conversation_id (added after the table first shipped) | |
| try: | |
| conn.execute(text("ALTER TABLE chat_messages ADD COLUMN IF NOT EXISTS conversation_id UUID;")) | |
| except Exception: | |
| pass | |
| # Ensure chat_messages has tokens_used (added after the table first shipped) | |
| try: | |
| conn.execute(text("ALTER TABLE chat_messages ADD COLUMN IF NOT EXISTS tokens_used INTEGER NOT NULL DEFAULT 0;")) | |
| except Exception: | |
| pass | |
| # Ensure users has plan/premium_renews_at (added after the table first shipped) | |
| try: | |
| conn.execute(text("ALTER TABLE users ADD COLUMN IF NOT EXISTS plan VARCHAR(20) NOT NULL DEFAULT 'free';")) | |
| except Exception: | |
| pass | |
| try: | |
| conn.execute(text("ALTER TABLE users ADD COLUMN IF NOT EXISTS premium_renews_at TIMESTAMPTZ;")) | |
| except Exception: | |
| pass | |
| except Exception as e: | |
| logging.error(f"Error initializing database: {e}") | |
| app = FastAPI( | |
| title=settings.PROJECT_NAME, | |
| openapi_url=f"{settings.API_V1_STR}/openapi.json" | |
| ) | |
| # CORS Middleware configurations (Security Guidelines) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=settings.BACKEND_CORS_ORIGINS, | |
| allow_credentials=True, | |
| allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], | |
| allow_headers=["*"], | |
| ) | |
| from fastapi.staticfiles import StaticFiles | |
| import os | |
| # Register routers | |
| app.include_router(api_router, prefix=settings.API_V1_STR) | |
| # Mount local storage folder as static files if mode is local | |
| if settings.STORAGE_MODE == "local": | |
| os.makedirs(settings.UPLOAD_DIR, exist_ok=True) | |
| app.mount("/static", StaticFiles(directory=settings.UPLOAD_DIR), name="static") | |
| # Global Exception Handler to avoid leaking internals (Security Guidelines) | |
| def global_exception_handler(request: Request, exc: Exception): | |
| logging.error(f"Internal error occurred on {request.url.path}: {exc}", exc_info=True) | |
| return JSONResponse( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| content={"detail": "Có lỗi hệ thống xảy ra. Vui lòng thử lại sau."} | |
| ) | |
| def health_check(): | |
| return {"status": "healthy"} | |