Spaces:
Sleeping
Sleeping
| """ | |
| Apl_GS API β FastAPI Application Entry Point | |
| Run: | |
| python app.py | |
| Or directly with uvicorn: | |
| uvicorn app:app --host 0.0.0.0 --port 5000 --reload | |
| API Docs: | |
| http://localhost:5000/docs (Swagger UI) | |
| http://localhost:5000/redoc (ReDoc) | |
| Architecture Reference: | |
| insights/architecture_rule.md | |
| """ | |
| import os | |
| import logging | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from dotenv import load_dotenv | |
| # Load environment variables FIRST (before any config imports) | |
| load_dotenv() | |
| from web.route import router | |
| from config.rate_limiter import rate_limit_middleware | |
| from config.database_config import init_db, close_db | |
| # ββ Logging ββ | |
| logging.basicConfig( | |
| level=os.getenv("LOG_LEVEL", "INFO"), | |
| format="%(asctime)s β %(name)s β %(levelname)s β %(message)s", | |
| ) | |
| logger = logging.getLogger(__name__) | |
| # ββ App Metadata ββ | |
| APP_NAME = os.getenv("APP_NAME", "Apl_GS API") | |
| APP_VERSION = "1.0.0" | |
| APP_ENV = os.getenv("APP_ENV", "development") | |
| APP_DEBUG = os.getenv("APP_DEBUG", "False").lower() == "true" | |
| # ββ Lifespan (startup + shutdown) ββ | |
| async def lifespan(app: FastAPI): | |
| """Application lifecycle β runs on startup and shutdown.""" | |
| # ββ STARTUP ββ | |
| logger.info(f"π Starting {APP_NAME} v{APP_VERSION}") | |
| logger.info(f"π Environment: {APP_ENV}") | |
| logger.info(f"π§ Debug mode: {APP_DEBUG}") | |
| logger.info(f"π Port: {os.getenv('PORT', '5000')}") | |
| # Initialize database tables | |
| try: | |
| await init_db() | |
| logger.info("β Database initialized successfully") | |
| except Exception as e: | |
| logger.error(f"β Database initialization failed: {e}") | |
| logger.warning("β οΈ API will start but database operations will fail") | |
| logger.warning("β οΈ Make sure PostgreSQL 15+ is installed and running!") | |
| yield # Application runs here | |
| # ββ SHUTDOWN ββ | |
| logger.info("π Shutting down Apl_GS API") | |
| await close_db() | |
| # ββ Create FastAPI Instance ββ | |
| app = FastAPI( | |
| title=APP_NAME, | |
| version=APP_VERSION, | |
| description=( | |
| "Apl_GS Backend API β Visit & Checklist Management System.\n\n" | |
| "**No authentication required** β protected by rate limiter.\n\n" | |
| "Built with FastAPI + PostgreSQL 15+.\n\n" | |
| "π Architecture Reference: `insights/architecture_rule.md`" | |
| ), | |
| docs_url="/docs", | |
| redoc_url="/redoc", | |
| openapi_url="/openapi.json", | |
| lifespan=lifespan, | |
| ) | |
| # ββ CORS Middleware ββ | |
| cors_origins = os.getenv( | |
| "CORS_ORIGINS", "http://localhost" | |
| ).split(",") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=[origin.strip() for origin in cors_origins], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # ββ Rate Limiter Middleware ββ | |
| app.middleware("http")(rate_limit_middleware) | |
| # ββ Include API Routes ββ | |
| app.include_router(router) | |
| # ββ Root Endpoint ββ | |
| async def root(): | |
| """ | |
| Root endpoint β returns API info, version, and documentation links. | |
| """ | |
| return { | |
| "status": "success", | |
| "data": { | |
| "name": APP_NAME, | |
| "version": APP_VERSION, | |
| "environment": APP_ENV, | |
| "docs": "/docs", | |
| "redoc": "/redoc", | |
| "health": "/api/v1/health", | |
| }, | |
| "message": "Apl_GS API is running", | |
| } | |
| # ββ Global Exception Handler ββ | |
| async def global_exception_handler(request, exc): | |
| """Handle unexpected exceptions gracefully.""" | |
| logger.error(f"Unhandled exception: {exc}", exc_info=True) | |
| return JSONResponse( | |
| status_code=500, | |
| content={ | |
| "status": "error", | |
| "error": { | |
| "code": "INTERNAL_ERROR", | |
| "message": "An unexpected error occurred", | |
| "details": str(exc) if APP_DEBUG else None, | |
| }, | |
| }, | |
| ) | |
| # ββ Run with Uvicorn ββ | |
| if __name__ == "__main__": | |
| import uvicorn | |
| host = os.getenv("HOST", "0.0.0.0") | |
| port = int(os.getenv("PORT", "5000")) | |
| logger.info(f"π Running on http://{host}:{port}") | |
| logger.info(f"π Swagger UI: http://{host}:{port}/docs") | |
| logger.info(f"π ReDoc: http://{host}:{port}/redoc") | |
| uvicorn.run( | |
| "app:app", | |
| host=host, | |
| port=port, | |
| reload=(APP_ENV == "development"), | |
| log_level=os.getenv("LOG_LEVEL", "info").lower(), | |
| ) | |