Nagesh Muralidhar commited on
Commit
1700fb6
·
1 Parent(s): 2251ba3

Fix frontend HTML serving with improved app architecture

Browse files
Files changed (1) hide show
  1. app.py +60 -95
app.py CHANGED
@@ -46,12 +46,45 @@ 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
- # Create a FastAPI app - either the main one or an error one
50
- from fastapi import FastAPI, Request
51
- from fastapi.responses import HTMLResponse, JSONResponse, FileResponse
52
  from fastapi.staticfiles import StaticFiles
53
  from fastapi.middleware.cors import CORSMiddleware
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  # Check if static directory exists with index.html
56
  static_index_exists = static_path.exists() and index_path.exists()
57
  logger.info(f"Static path exists: {static_path.exists()}")
@@ -60,8 +93,14 @@ if static_path.exists():
60
  logger.info(f"Static index exists: {index_path.exists()}")
61
 
62
  try:
63
- # Try to import the main app
64
- from backend.app.main import app
 
 
 
 
 
 
65
 
66
  # Add CORS middleware
67
  app.add_middleware(
@@ -72,102 +111,28 @@ try:
72
  allow_headers=["*"],
73
  )
74
 
75
- # Add an index route to check if the API is accessible
76
- @app.get("/api/status")
77
- async def status():
78
- return {"status": "ok", "message": "PodCraft API is running"}
79
-
80
- # Override the root route to serve the frontend
81
- @app.get("/", response_class=HTMLResponse)
82
- async def read_root():
83
- # If index.html exists, return it directly using FileResponse
84
- if index_path.exists():
85
- logger.info(f"Serving index.html from {index_path}")
86
- return FileResponse(index_path)
87
- else:
88
- logger.warning("index.html not found, returning fallback HTML")
89
- return """
90
- <html>
91
- <head>
92
- <title>PodCraft API</title>
93
- <style>
94
- body { font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f8f9fa; }
95
- .container { max-width: 800px; padding: 2rem; background-color: white; border-radius: 0.5rem; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
96
- h1 { color: #6366F1; }
97
- pre { background-color: #f5f5f5; padding: 1rem; border-radius: 0.25rem; overflow: auto; }
98
- </style>
99
- </head>
100
- <body>
101
- <div class="container">
102
- <h1>PodCraft API</h1>
103
- <p>The PodCraft API is running, but the frontend static files were not found.</p>
104
- <p>Static directory: <code>./static</code></p>
105
- <p>Static directory exists: <code>{static_path.exists()}</code></p>
106
- <p>If you need to access the API directly, you can use the following endpoints:</p>
107
- <ul>
108
- <li><code>/api/status</code> - Check API status</li>
109
- <li><code>/docs</code> - API documentation</li>
110
- </ul>
111
- </div>
112
- </body>
113
- </html>
114
- """
115
-
116
- # Mount static files
117
- # First, make sure we're not serving the root path via StaticFiles
118
- @app.get("/static/{path:path}")
119
- async def serve_static(path: str):
120
- file_path = static_path / path
121
- if file_path.exists() and file_path.is_file():
122
- return FileResponse(file_path)
123
- return {"error": "File not found"}
124
 
125
  app_to_run = app
126
- logger.info("Using main application")
127
 
128
  except Exception as e:
129
- # If there's an error, create a minimal FastAPI app
130
- logger.error(f"Error initializing main app: {str(e)}")
131
- error_app = FastAPI()
132
-
133
- @error_app.get("/", response_class=HTMLResponse)
134
- async def root():
135
- return f"""
136
- <html>
137
- <head>
138
- <title>PodCraft - Error</title>
139
- <style>
140
- body {{ font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f8f9fa; }}
141
- .container {{ max-width: 800px; padding: 2rem; background-color: white; border-radius: 0.5rem; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }}
142
- h1 {{ color: #d32f2f; }}
143
- pre {{ background-color: #f5f5f5; padding: 1rem; border-radius: 0.25rem; overflow: auto; }}
144
- </style>
145
- </head>
146
- <body>
147
- <div class="container">
148
- <h1>PodCraft Error</h1>
149
- <p>An error occurred while starting the application:</p>
150
- <pre>{str(e)}</pre>
151
- <p>Please check your environment variables and configuration.</p>
152
- <p>MongoDB URL format should be: <code>mongodb+srv://username:[email protected]/...</code></p>
153
- <p>API keys should be properly formatted and valid.</p>
154
- <p>Static directory exists: <code>{static_path.exists()}</code></p>
155
- {f"<p>Static directory contents: <code>{os.listdir(static_path)}</code></p>" if static_path.exists() else ""}
156
- <p>Static index exists: <code>{static_index_exists}</code></p>
157
- </div>
158
- </body>
159
- </html>
160
- """
161
 
162
- @error_app.get("/static/{path:path}")
163
- async def serve_static(path: str):
164
- file_path = static_path / path
165
- if file_path.exists() and file_path.is_file():
166
- return FileResponse(file_path)
167
- return {"error": "File not found"}
 
168
 
169
- app_to_run = error_app
170
- logger.info("Using error application")
171
 
172
  # For Hugging Face Spaces - expose the app
173
  if __name__ == "__main__":
 
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
+ # Create our own FastAPI app first
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
+ # Create our own app that will handle frontend routes
56
+ frontend_app = FastAPI(title="PodCraft Frontend")
57
+
58
+ # Add CORS middleware
59
+ frontend_app.add_middleware(
60
+ CORSMiddleware,
61
+ allow_origins=["*"],
62
+ allow_credentials=True,
63
+ allow_methods=["*"],
64
+ allow_headers=["*"],
65
+ )
66
+
67
+ # Mount static directory
68
+ if static_path.exists():
69
+ frontend_app.mount("/static", StaticFiles(directory=str(static_path)), name="static")
70
+
71
+ # Root route handler
72
+ @frontend_app.get("/", response_class=HTMLResponse)
73
+ async def read_root():
74
+ logger.info(f"Serving index.html from {index_path}")
75
+ # Read the file contents directly
76
+ if index_path.exists():
77
+ with open(index_path, "r") as f:
78
+ content = f.read()
79
+ return HTMLResponse(content=content)
80
+ else:
81
+ return HTMLResponse(content="Index file not found", status_code=404)
82
+
83
+ # API status endpoint
84
+ @frontend_app.get("/api/status")
85
+ async def status():
86
+ return {"status": "ok", "message": "PodCraft API is running"}
87
+
88
  # Check if static directory exists with index.html
89
  static_index_exists = static_path.exists() and index_path.exists()
90
  logger.info(f"Static path exists: {static_path.exists()}")
 
93
  logger.info(f"Static index exists: {index_path.exists()}")
94
 
95
  try:
96
+ # Try to import the backend app
97
+ from backend.app.main import app as backend_app
98
+
99
+ # Now create a merged app that prioritizes frontend routes
100
+ app = FastAPI(title="PodCraft")
101
+
102
+ # Add frontend app routes to the main app
103
+ app.mount("/", frontend_app)
104
 
105
  # Add CORS middleware
106
  app.add_middleware(
 
111
  allow_headers=["*"],
112
  )
113
 
114
+ # Forward specific backend API routes
115
+ @app.get("/api/{path:path}")
116
+ async def api_route(request: Request, path: str):
117
+ return await backend_app.handle_request(request)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  app_to_run = app
120
+ logger.info("Using merged application (frontend + backend)")
121
 
122
  except Exception as e:
123
+ # If there's an error, use just the frontend app
124
+ logger.error(f"Error initializing backend app: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
+ # Add error handler to frontend app
127
+ @frontend_app.get("/api/{path:path}")
128
+ async def api_error(path: str):
129
+ return {
130
+ "error": "Backend API not available",
131
+ "message": str(e)
132
+ }
133
 
134
+ app_to_run = frontend_app
135
+ logger.info("Using frontend application only due to backend error")
136
 
137
  # For Hugging Face Spaces - expose the app
138
  if __name__ == "__main__":