import os import logging from fastapi.staticfiles import StaticFiles from fastapi import Request from fastapi.responses import FileResponse, JSONResponse from ylff.server import app logger = logging.getLogger(__name__) # Mount static files (Next.js exported assets) # We mount this AFTER the API routes defined in `ylff.server` so that API routes take precedence. # However, FastAPI mounts match by path. "/" matches everything. # So we need to be careful. # But `StaticFiles` only handles requests if the file exists? No, it catches everything under mount path. # So requests to /api/... might get caught if we mount at "/"? # NO: FastAPI router matches first. # Wait. `app = create_app()` includes routers. # If we add mount("/") now, it acts as a catch-all? # Actually, explicitly defined routes (like /api/v1/...) are checked before mounts? # It depends on order... but `app.mount()` typically adds to the routes list. # Since `app` is already created with API routes, appending mount("/") usually works as fallback. STATIC_DIR = "/app/static" if os.path.exists(STATIC_DIR): logger.info(f"Mounting static files from {STATIC_DIR}") # 1. Mount specific assets first app.mount("/_next", StaticFiles(directory=f"{STATIC_DIR}/_next"), name="next-static") # 2. Mount root for everything else (index.html, favicon, etc) # We must be careful not to shadow /api. # FastAPI docs say: "The order matters. Routes are matched in order." # Since API routes were added in `create_app` (imported above), they are already in `app.router.routes`. # `app.mount` adds to the end. So it effectively acts as fallback. app.mount("/", StaticFiles(directory=STATIC_DIR, html=True), name="root-static") else: logger.warning(f"Static directory {STATIC_DIR} not found. Running in API-only mode.") # Just to be safe, we can add a simple root endpoint ONLY if static dir is missing # (which StaticFiles handles otherwise) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)