Spaces:
Sleeping
Sleeping
Nagesh Muralidhar
commited on
Commit
·
2784e84
1
Parent(s):
fee9ffa
addin app.py
Browse files
app.py
CHANGED
|
@@ -46,17 +46,34 @@ if not index_path.exists():
|
|
| 46 |
os.environ["MONGODB_CONNECT_TIMEOUT_MS"] = "5000" # 5 seconds timeout
|
| 47 |
os.environ["MONGODB_SERVER_SELECTION_TIMEOUT_MS"] = "5000" # 5 seconds timeout
|
| 48 |
|
| 49 |
-
#
|
| 50 |
-
from fastapi import FastAPI, Request, HTTPException
|
| 51 |
-
from fastapi.responses import HTMLResponse, JSONResponse, FileResponse, Response
|
| 52 |
from fastapi.staticfiles import StaticFiles
|
| 53 |
from fastapi.middleware.cors import CORSMiddleware
|
| 54 |
|
| 55 |
-
#
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
# Add CORS middleware
|
| 59 |
-
|
| 60 |
CORSMiddleware,
|
| 61 |
allow_origins=["*"],
|
| 62 |
allow_credentials=True,
|
|
@@ -64,32 +81,19 @@ frontend_app.add_middleware(
|
|
| 64 |
allow_headers=["*"],
|
| 65 |
)
|
| 66 |
|
| 67 |
-
#
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
logger.info(f"Static index exists: {index_path.exists()}")
|
| 73 |
-
|
| 74 |
-
# Root route handler - must come before mounting static files
|
| 75 |
-
@frontend_app.get("/", response_class=HTMLResponse)
|
| 76 |
-
async def read_root():
|
| 77 |
-
logger.info(f"Serving index.html from {index_path}")
|
| 78 |
-
# Read the file contents directly
|
| 79 |
-
if index_path.exists():
|
| 80 |
-
with open(index_path, "r") as f:
|
| 81 |
-
content = f.read()
|
| 82 |
-
return HTMLResponse(content=content)
|
| 83 |
-
else:
|
| 84 |
-
return HTMLResponse(content="Index file not found", status_code=404)
|
| 85 |
|
| 86 |
# API status endpoint
|
| 87 |
-
@
|
| 88 |
async def status():
|
| 89 |
return {"status": "ok", "message": "PodCraft API is running"}
|
| 90 |
|
| 91 |
-
# Serve
|
| 92 |
-
@
|
| 93 |
async def serve_assets(file_path: str):
|
| 94 |
file_full_path = static_path / "assets" / file_path
|
| 95 |
|
|
@@ -113,75 +117,27 @@ async def serve_assets(file_path: str):
|
|
| 113 |
logger.info(f"Serving asset: {file_path} with content-type: {content_type}")
|
| 114 |
return FileResponse(file_full_path, media_type=content_type)
|
| 115 |
|
| 116 |
-
#
|
| 117 |
if static_path.exists():
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
# Catch-all route
|
| 121 |
-
@
|
| 122 |
-
async def catch_all(full_path: str):
|
| 123 |
-
# Skip API paths
|
| 124 |
-
if full_path.startswith("api/") or full_path
|
| 125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
with open(index_path, "r") as f:
|
| 131 |
-
content = f.read()
|
| 132 |
-
return HTMLResponse(content=content)
|
| 133 |
-
else:
|
| 134 |
-
return HTMLResponse(content="Index file not found", status_code=404)
|
| 135 |
-
|
| 136 |
-
try:
|
| 137 |
-
# Try to import the backend app
|
| 138 |
-
from backend.app.main import app as backend_app
|
| 139 |
-
|
| 140 |
-
# Now create a merged app that prioritizes frontend routes
|
| 141 |
-
app = FastAPI(title="PodCraft")
|
| 142 |
-
|
| 143 |
-
# Add CORS middleware
|
| 144 |
-
app.add_middleware(
|
| 145 |
-
CORSMiddleware,
|
| 146 |
-
allow_origins=["*"],
|
| 147 |
-
allow_credentials=True,
|
| 148 |
-
allow_methods=["*"],
|
| 149 |
-
allow_headers=["*"],
|
| 150 |
-
)
|
| 151 |
-
|
| 152 |
-
# Include the backend app routes
|
| 153 |
-
# This imports all routes from the backend_app into our main app
|
| 154 |
-
from fastapi import APIRouter
|
| 155 |
-
backend_router = APIRouter()
|
| 156 |
-
|
| 157 |
-
# Import all routes from backend_app
|
| 158 |
-
for route in backend_app.routes:
|
| 159 |
-
backend_router.routes.append(route)
|
| 160 |
-
|
| 161 |
-
# Add the backend routes
|
| 162 |
-
app.include_router(backend_router)
|
| 163 |
-
|
| 164 |
-
# Mount the frontend app at the root - this should be last
|
| 165 |
-
# so that API routes take precedence but frontend handles all other routes
|
| 166 |
-
app.mount("/", frontend_app)
|
| 167 |
-
|
| 168 |
-
app_to_run = app
|
| 169 |
-
logger.info("Using merged application (frontend + backend)")
|
| 170 |
-
|
| 171 |
-
except Exception as e:
|
| 172 |
-
# If there's an error, use just the frontend app
|
| 173 |
-
logger.error(f"Error initializing backend app: {str(e)}")
|
| 174 |
-
|
| 175 |
-
# Add error handler to frontend app
|
| 176 |
-
@frontend_app.get("/api/{path:path}")
|
| 177 |
-
async def api_error(path: str):
|
| 178 |
-
return {
|
| 179 |
-
"error": "Backend API not available",
|
| 180 |
-
"message": str(e)
|
| 181 |
-
}
|
| 182 |
|
| 183 |
-
|
| 184 |
-
|
| 185 |
|
| 186 |
# For Hugging Face Spaces - expose the app
|
| 187 |
if __name__ == "__main__":
|
|
@@ -191,4 +147,4 @@ if __name__ == "__main__":
|
|
| 191 |
host = os.environ.get("HOST", "0.0.0.0")
|
| 192 |
|
| 193 |
logger.info(f"Starting server on {host}:{port}")
|
| 194 |
-
uvicorn.run(
|
|
|
|
| 46 |
os.environ["MONGODB_CONNECT_TIMEOUT_MS"] = "5000" # 5 seconds timeout
|
| 47 |
os.environ["MONGODB_SERVER_SELECTION_TIMEOUT_MS"] = "5000" # 5 seconds timeout
|
| 48 |
|
| 49 |
+
# Import FastAPI and related modules
|
| 50 |
+
from fastapi import FastAPI, Request, HTTPException, Depends
|
| 51 |
+
from fastapi.responses import HTMLResponse, JSONResponse, FileResponse, Response, RedirectResponse
|
| 52 |
from fastapi.staticfiles import StaticFiles
|
| 53 |
from fastapi.middleware.cors import CORSMiddleware
|
| 54 |
|
| 55 |
+
# Function to read index.html content
|
| 56 |
+
def get_index_html():
|
| 57 |
+
if index_path.exists():
|
| 58 |
+
with open(index_path, "r") as f:
|
| 59 |
+
return f.read()
|
| 60 |
+
else:
|
| 61 |
+
return "<html><body><h1>Index file not found</h1></body></html>"
|
| 62 |
+
|
| 63 |
+
try:
|
| 64 |
+
# Try to import the backend app but don't use it directly
|
| 65 |
+
import backend.app.main
|
| 66 |
+
logger.info("Backend module imported successfully")
|
| 67 |
+
backend_available = True
|
| 68 |
+
except Exception as e:
|
| 69 |
+
logger.error(f"Error importing backend module: {str(e)}")
|
| 70 |
+
backend_available = False
|
| 71 |
+
|
| 72 |
+
# Create the main application
|
| 73 |
+
app = FastAPI(title="PodCraft")
|
| 74 |
|
| 75 |
# Add CORS middleware
|
| 76 |
+
app.add_middleware(
|
| 77 |
CORSMiddleware,
|
| 78 |
allow_origins=["*"],
|
| 79 |
allow_credentials=True,
|
|
|
|
| 81 |
allow_headers=["*"],
|
| 82 |
)
|
| 83 |
|
| 84 |
+
# Define the root route that directly serves index.html
|
| 85 |
+
@app.get("/", response_class=HTMLResponse)
|
| 86 |
+
async def root():
|
| 87 |
+
logger.info("Root route accessed, serving index.html")
|
| 88 |
+
return HTMLResponse(content=get_index_html())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
# API status endpoint
|
| 91 |
+
@app.get("/api/status")
|
| 92 |
async def status():
|
| 93 |
return {"status": "ok", "message": "PodCraft API is running"}
|
| 94 |
|
| 95 |
+
# Serve static assets directory with correct content types
|
| 96 |
+
@app.get("/assets/{file_path:path}")
|
| 97 |
async def serve_assets(file_path: str):
|
| 98 |
file_full_path = static_path / "assets" / file_path
|
| 99 |
|
|
|
|
| 117 |
logger.info(f"Serving asset: {file_path} with content-type: {content_type}")
|
| 118 |
return FileResponse(file_full_path, media_type=content_type)
|
| 119 |
|
| 120 |
+
# Mount the static directory for other static files
|
| 121 |
if static_path.exists():
|
| 122 |
+
app.mount("/static", StaticFiles(directory=str(static_path)), name="static")
|
| 123 |
+
|
| 124 |
+
# Catch-all route for client-side routing in the React app
|
| 125 |
+
@app.get("/{full_path:path}")
|
| 126 |
+
async def catch_all(full_path: str, request: Request):
|
| 127 |
+
# Skip API paths and redirect them to the backend
|
| 128 |
+
if full_path.startswith("api/") or full_path == "docs" or full_path == "openapi.json":
|
| 129 |
+
if backend_available:
|
| 130 |
+
# Use the backend.app.main module's routes
|
| 131 |
+
return backend.app.main.app.get(full_path)
|
| 132 |
+
else:
|
| 133 |
+
return {"error": "Backend API not available"}
|
| 134 |
|
| 135 |
+
# Skip static file paths
|
| 136 |
+
if full_path.startswith("static/") or full_path.startswith("assets/"):
|
| 137 |
+
raise HTTPException(status_code=404, detail="Not found")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
+
logger.info(f"Catch-all route hit for path: {full_path}, serving index.html for client-side routing")
|
| 140 |
+
return HTMLResponse(content=get_index_html())
|
| 141 |
|
| 142 |
# For Hugging Face Spaces - expose the app
|
| 143 |
if __name__ == "__main__":
|
|
|
|
| 147 |
host = os.environ.get("HOST", "0.0.0.0")
|
| 148 |
|
| 149 |
logger.info(f"Starting server on {host}:{port}")
|
| 150 |
+
uvicorn.run(app, host=host, port=port)
|