import os import sys import shutil import logging from pathlib import Path # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Add the backend directory to the Python path sys.path.append(os.path.abspath("backend")) # Create necessary directories if they don't exist os.makedirs("./temp_audio", exist_ok=True) os.makedirs("./temp", exist_ok=True) os.makedirs("./static", exist_ok=True) # Check for index.html and create a simple one if it doesn't exist static_path = Path("./static") index_path = static_path / "index.html" if not index_path.exists(): logger.warning("index.html not found in static directory, creating a simple one") with open(index_path, "w") as f: f.write(""" PodCraft API

PodCraft API

The PodCraft API is running. You can access the API at /docs.

API Status: /api/status

""") # Set environment variables for MongoDB connection timeout os.environ["MONGODB_CONNECT_TIMEOUT_MS"] = "5000" # 5 seconds timeout os.environ["MONGODB_SERVER_SELECTION_TIMEOUT_MS"] = "5000" # 5 seconds timeout # Create our own FastAPI app first from fastapi import FastAPI, Request, HTTPException from fastapi.responses import HTMLResponse, JSONResponse, FileResponse, Response from fastapi.staticfiles import StaticFiles from fastapi.middleware.cors import CORSMiddleware # Create our own app that will handle frontend routes frontend_app = FastAPI(title="PodCraft Frontend") # Add CORS middleware frontend_app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Check if static directory exists with index.html static_index_exists = static_path.exists() and index_path.exists() logger.info(f"Static path exists: {static_path.exists()}") if static_path.exists(): logger.info(f"Static directory contents: {os.listdir(static_path)}") logger.info(f"Static index exists: {index_path.exists()}") # Root route handler - must come before mounting static files @frontend_app.get("/", response_class=HTMLResponse) async def read_root(): logger.info(f"Serving index.html from {index_path}") # Read the file contents directly if index_path.exists(): with open(index_path, "r") as f: content = f.read() return HTMLResponse(content=content) else: return HTMLResponse(content="Index file not found", status_code=404) # API status endpoint @frontend_app.get("/api/status") async def status(): return {"status": "ok", "message": "PodCraft API is running"} # Serve specific file types with correct Content-Type @frontend_app.get("/assets/{file_path:path}") async def serve_assets(file_path: str): file_full_path = static_path / "assets" / file_path if not file_full_path.exists() or not file_full_path.is_file(): logger.warning(f"Asset file not found: {file_full_path}") raise HTTPException(status_code=404, detail="Asset file not found") # Determine content type based on file extension content_type = None if file_path.endswith(".js"): content_type = "application/javascript" elif file_path.endswith(".css"): content_type = "text/css" elif file_path.endswith(".svg"): content_type = "image/svg+xml" elif file_path.endswith(".png"): content_type = "image/png" elif file_path.endswith(".jpg") or file_path.endswith(".jpeg"): content_type = "image/jpeg" logger.info(f"Serving asset: {file_path} with content-type: {content_type}") return FileResponse(file_full_path, media_type=content_type) # Now mount the static directory AFTER defining the root handler if static_path.exists(): frontend_app.mount("/static", StaticFiles(directory=str(static_path)), name="static") # Catch-all route to serve index.html for client-side routing @frontend_app.get("/{full_path:path}") async def catch_all(full_path: str): # Skip API paths if full_path.startswith("api/") or full_path.startswith("docs") or full_path.startswith("openapi.json"): raise HTTPException(status_code=404, detail="Not found") logger.info(f"Catch-all route hit for path: {full_path}, serving index.html") # For any other path, serve index.html to support client-side routing if index_path.exists(): with open(index_path, "r") as f: content = f.read() return HTMLResponse(content=content) else: return HTMLResponse(content="Index file not found", status_code=404) try: # Try to import the backend app from backend.app.main import app as backend_app # Now create a merged app that prioritizes frontend routes app = FastAPI(title="PodCraft") # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include the backend app routes # This imports all routes from the backend_app into our main app from fastapi import APIRouter backend_router = APIRouter() # Import all routes from backend_app for route in backend_app.routes: backend_router.routes.append(route) # Add the backend routes app.include_router(backend_router) # Mount the frontend app at the root - this should be last # so that API routes take precedence but frontend handles all other routes app.mount("/", frontend_app) app_to_run = app logger.info("Using merged application (frontend + backend)") except Exception as e: # If there's an error, use just the frontend app logger.error(f"Error initializing backend app: {str(e)}") # Add error handler to frontend app @frontend_app.get("/api/{path:path}") async def api_error(path: str): return { "error": "Backend API not available", "message": str(e) } app_to_run = frontend_app logger.info("Using frontend application only due to backend error") # For Hugging Face Spaces - expose the app if __name__ == "__main__": import uvicorn port = int(os.environ.get("PORT", 7860)) host = os.environ.get("HOST", "0.0.0.0") logger.info(f"Starting server on {host}:{port}") uvicorn.run(app_to_run, host=host, port=port)