Nagesh Muralidhar
Fix frontend build and serving process
fee9ffa
raw
history blame
7.03 kB
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("""<!DOCTYPE html>
<html>
<head>
<title>PodCraft API</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f8f9fa; }
.container { max-width: 800px; padding: 2rem; background-color: white; border-radius: 0.5rem; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
h1 { color: #6366F1; }
pre { background-color: #f5f5f5; padding: 1rem; border-radius: 0.25rem; overflow: auto; }
</style>
</head>
<body>
<div class="container">
<h1>PodCraft API</h1>
<p>The PodCraft API is running. You can access the API at <a href="/docs">/docs</a>.</p>
<p>API Status: <a href="/api/status">/api/status</a></p>
</div>
</body>
</html>""")
# 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)