from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse from app.api.artifacts import router as artifacts_router from app.api.seed import router as seed_router from app.database import init_db from app.config import settings import logging import os # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # Create FastAPI app app = FastAPI( title="Warehouse13", description="Enterprise Test Artifact Storage - API for storing and querying test artifacts including CSV, JSON, binary files, and packet captures", version="1.0.0", docs_url="/docs", redoc_url="/redoc" ) # Configure CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(artifacts_router) app.include_router(seed_router) # Static directory setup static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "static") @app.on_event("startup") async def startup_event(): """Initialize database on startup""" logger.info("Initializing database...") init_db() logger.info(f"Deployment mode: {settings.deployment_mode}") logger.info(f"Using storage backend: {settings.storage_backend}") logger.info("Application started successfully") @app.get("/api") async def api_root(): """API root endpoint""" return { "message": "Warehouse13 - Enterprise Test Artifact Storage", "version": "1.0.0", "docs": "/docs", "deployment_mode": settings.deployment_mode, "storage_backend": settings.storage_backend } @app.get("/") async def ui_root(): """Serve the UI""" index_path = os.path.join(static_dir, "index.html") if os.path.exists(index_path): return FileResponse(index_path) else: return { "message": "Warehouse13 - Enterprise Test Artifact Storage", "version": "1.0.0", "docs": "/docs", "ui": "UI not found. Serving API only.", "deployment_mode": settings.deployment_mode, "storage_backend": settings.storage_backend } # Catch-all route for Angular SPA routing - must be last @app.get("/{full_path:path}") async def serve_spa(full_path: str): """Serve Angular SPA static files and handle client-side routing""" # Try to serve static file first (JS, CSS, images, etc.) file_path = os.path.join(static_dir, full_path) if os.path.exists(file_path) and os.path.isfile(file_path): return FileResponse(file_path) # For all other routes (Angular client-side routes), serve index.html index_path = os.path.join(static_dir, "index.html") if os.path.exists(index_path): return FileResponse(index_path) else: return { "message": "Warehouse13 - Enterprise Test Artifact Storage", "version": "1.0.0", "docs": "/docs", "ui": "UI not found. Serving API only.", "deployment_mode": settings.deployment_mode, "storage_backend": settings.storage_backend } @app.get("/health") async def health_check(): """Health check endpoint""" return {"status": "healthy"} if __name__ == "__main__": import uvicorn uvicorn.run( "app.main:app", host=settings.api_host, port=settings.api_port, reload=True )