Spaces:
Running
Running
File size: 3,902 Bytes
02eac4b bf6e620 02eac4b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
import logging
import os
from pathlib import Path
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
# Import the existing API
from src.api import app as api_app
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[logging.StreamHandler(), logging.FileHandler("server.log")],
)
logger = logging.getLogger(__name__)
# Create a new FastAPI app that combines API and frontend
app = FastAPI(
title="LeRobot Arena Transport Server with UI",
description="Combined API and web interface for LeRobot Arena transport server",
version="2.0.0",
)
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Add the health endpoint BEFORE other routes to avoid conflicts
@app.get("/health")
async def health_check():
return {
"status": "healthy",
"server_running": True,
"frontend_enabled": os.getenv("SERVE_FRONTEND", "false").lower() == "true",
"api_available": True,
}
# Mount the API under /api prefix
app.mount("/api", api_app)
# Check if we should serve frontend
serve_frontend = os.getenv("SERVE_FRONTEND", "false").lower() == "true"
if serve_frontend:
# Get the frontend static files path
frontend_path = Path(__file__).parent.parent / "static-frontend"
if frontend_path.exists():
logger.info(f"Serving frontend from: {frontend_path}")
# Mount static files (JS, CSS, etc.)
app.mount("/static", StaticFiles(directory=frontend_path), name="static")
# Serve the main app for all other routes (SPA)
@app.get("/{full_path:path}")
async def serve_frontend_app(full_path: str):
"""Serve the SvelteKit app for all non-API routes."""
# Don't serve frontend for API routes
if full_path.startswith("api/"):
return {"error": "API route not found"}
# Check if requesting a specific file
file_path = frontend_path / full_path
if file_path.is_file():
return FileResponse(file_path)
# For all other routes, serve the main index.html (SPA behavior)
index_path = frontend_path / "index.html"
if index_path.exists():
return FileResponse(index_path)
return {"error": "Frontend not available"}
else:
logger.warning(f"Frontend path not found: {frontend_path}")
@app.get("/")
async def no_frontend():
return {
"message": "LeRobot Arena Transport Server",
"frontend": "not available",
"api": "available at /api/",
"docs": "available at /api/docs",
}
else:
@app.get("/")
async def api_only():
return {
"message": "LeRobot Arena Transport Server - API Only",
"api": "available at /api/",
"docs": "available at /api/docs",
}
if __name__ == "__main__":
port = int(os.getenv("PORT", 7860))
host = os.getenv("HOST", "0.0.0.0")
logger.info("🤖 Starting LeRobot Arena Combined Server...")
logger.info(f" - API available at: http://{host}:{port}/api/")
logger.info(f" - API docs at: http://{host}:{port}/api/docs")
if serve_frontend:
logger.info(f" - Frontend available at: http://{host}:{port}/")
else:
logger.info(" - Frontend disabled (set SERVE_FRONTEND=true to enable)")
print(f"🤖 Starting LeRobot Arena Combined Server on {host}:{port}")
uvicorn.run(
"launch_with_ui:app",
host=host,
port=port,
reload=False,
log_level="info",
)
|