Nagesh Muralidhar commited on
Commit
f8108f2
·
1 Parent(s): e01254e

Fix API calls from frontend by adding URL rewriting and proxy endpoints

Browse files
Files changed (1) hide show
  1. app.py +151 -28
app.py CHANGED
@@ -60,6 +60,15 @@ def get_index_html():
60
  else:
61
  return "<html><body><h1>Index file not found</h1></body></html>"
62
 
 
 
 
 
 
 
 
 
 
63
  # Create the main application
64
  app = FastAPI(title="PodCraft")
65
 
@@ -72,38 +81,20 @@ app.add_middleware(
72
  allow_headers=["*"],
73
  )
74
 
75
- # Try to load the backend app
76
- backend_app = None
77
- try:
78
- # Import the backend app
79
- from backend.app.main import app as backend_app
80
- logger.info("Backend module imported successfully")
81
-
82
- # Add all non-root routes from the backend app to our main app
83
- from fastapi.routing import APIRoute, APIRouter
84
-
85
- # Create a router for backend routes
86
- backend_router = APIRouter()
87
-
88
- # Add all routes from the backend app to our router
89
- for route in backend_app.routes:
90
- if not (isinstance(route, APIRoute) and route.path == "/"):
91
- # Add this route to our router
92
- logger.info(f"Adding backend route: {route.path}")
93
- backend_router.routes.append(route)
94
-
95
- # Include the backend router in our main app
96
- app.include_router(backend_router)
97
-
98
- except Exception as e:
99
- logger.error(f"Error importing backend module: {str(e)}")
100
- backend_app = None
101
-
102
  # Define the root route that directly serves index.html
103
  @app.get("/", response_class=HTMLResponse)
104
  async def root():
105
  logger.info("Root route accessed, serving index.html")
106
- return HTMLResponse(content=get_index_html())
 
 
 
 
 
 
 
 
 
107
 
108
  # API status endpoint
109
  @app.get("/api/status")
@@ -135,6 +126,130 @@ async def serve_assets(file_path: str):
135
  logger.info(f"Serving asset: {file_path} with content-type: {content_type}")
136
  return FileResponse(file_full_path, media_type=content_type)
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  # Mount the static directory for other static files
139
  if static_path.exists():
140
  app.mount("/static", StaticFiles(directory=str(static_path)), name="static")
@@ -142,6 +257,14 @@ if static_path.exists():
142
  # Catch-all route for client-side routing in the React app
143
  @app.get("/{full_path:path}")
144
  async def catch_all(full_path: str, request: Request):
 
 
 
 
 
 
 
 
145
  # Skip static file paths
146
  if full_path.startswith("static/") or full_path.startswith("assets/"):
147
  raise HTTPException(status_code=404, detail="Not found")
 
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
 
 
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
+ html_content = get_index_html()
89
+
90
+ # Check if this is the React app by looking for specific markers
91
+ if "<div id=\"root\"></div>" in html_content:
92
+ logger.info("Detected React app, injecting URL fixer")
93
+ # Inject our URL fixer script before the closing body tag
94
+ script_tag = '<script src="/api/fix-client-urls"></script>'
95
+ html_content = html_content.replace('</body>', f'{script_tag}</body>')
96
+
97
+ return HTMLResponse(content=html_content)
98
 
99
  # API status endpoint
100
  @app.get("/api/status")
 
126
  logger.info(f"Serving asset: {file_path} with content-type: {content_type}")
127
  return FileResponse(file_full_path, media_type=content_type)
128
 
129
+ # Special handlers for API routes that the React app calls directly
130
+ @app.post("/login")
131
+ async def login_proxy(request: Request):
132
+ logger.info("Received login request, proxying to backend")
133
+ if backend_available:
134
+ # Forward the request to the backend
135
+ try:
136
+ # Get the raw request body and headers
137
+ body = await request.body()
138
+ json_data = await request.json()
139
+
140
+ # Import the actual login route from backend
141
+ from backend.app.main import login
142
+
143
+ # Create a mock request with the same data
144
+ mock_request = Request(scope=request.scope)
145
+ setattr(mock_request, "_json", json_data)
146
+
147
+ # Call the backend login route directly
148
+ response = await login(mock_request)
149
+ return response
150
+ except Exception as e:
151
+ logger.error(f"Error proxying login request: {str(e)}")
152
+ return JSONResponse(
153
+ content={"error": "Login failed", "message": str(e)},
154
+ status_code=500
155
+ )
156
+ else:
157
+ return JSONResponse(
158
+ content={"error": "Backend API not available for login"},
159
+ status_code=503
160
+ )
161
+
162
+ @app.post("/signup")
163
+ async def signup_proxy(request: Request):
164
+ logger.info("Received signup request, proxying to backend")
165
+ if backend_available:
166
+ try:
167
+ # Get the JSON data from the request
168
+ json_data = await request.json()
169
+
170
+ # Import the actual signup route from backend
171
+ from backend.app.main import signup
172
+
173
+ # Call the backend signup route
174
+ response = await signup(json_data)
175
+ return response
176
+ except Exception as e:
177
+ logger.error(f"Error proxying signup request: {str(e)}")
178
+ return JSONResponse(
179
+ content={"error": "Signup failed", "message": str(e)},
180
+ status_code=500
181
+ )
182
+ else:
183
+ return JSONResponse(
184
+ content={"error": "Backend API not available for signup"},
185
+ status_code=503
186
+ )
187
+
188
+ @app.post("/token")
189
+ async def token_proxy(request: Request):
190
+ logger.info("Received token request, proxying to backend")
191
+ if backend_available:
192
+ try:
193
+ # Get form data from the request
194
+ form_data = await request.form()
195
+
196
+ # Import the actual token route from backend
197
+ from backend.app.main import login_for_access_token
198
+
199
+ # Call the backend token route
200
+ response = await login_for_access_token(form_data)
201
+ return response
202
+ except Exception as e:
203
+ logger.error(f"Error proxying token request: {str(e)}")
204
+ return JSONResponse(
205
+ content={"error": "Token request failed", "message": str(e)},
206
+ status_code=500
207
+ )
208
+ else:
209
+ return JSONResponse(
210
+ content={"error": "Backend API not available for token request"},
211
+ status_code=503
212
+ )
213
+
214
+ # Post-fix: Add a helper function to fix the client-side JS
215
+ @app.get("/api/fix-client-urls")
216
+ async def fix_client_urls():
217
+ """
218
+ This endpoint returns JavaScript to inject into the page that rewrites
219
+ hardcoded localhost URLs to relative URLs
220
+ """
221
+ return HTMLResponse(content="""
222
+ <script>
223
+ (function() {
224
+ console.log("URL Fixer running...");
225
+
226
+ // Override fetch to rewrite localhost URLs
227
+ const originalFetch = window.fetch;
228
+ window.fetch = function(url, options) {
229
+ if (typeof url === 'string' && url.includes('localhost:8000')) {
230
+ const newUrl = url.replace('http://localhost:8000', '');
231
+ console.log(`Rewriting URL from ${url} to ${newUrl}`);
232
+ return originalFetch(newUrl, options);
233
+ }
234
+ return originalFetch(url, options);
235
+ };
236
+
237
+ // Override XMLHttpRequest to rewrite localhost URLs
238
+ const originalOpen = XMLHttpRequest.prototype.open;
239
+ XMLHttpRequest.prototype.open = function(method, url, ...args) {
240
+ if (typeof url === 'string' && url.includes('localhost:8000')) {
241
+ const newUrl = url.replace('http://localhost:8000', '');
242
+ console.log(`Rewriting XHR URL from ${url} to ${newUrl}`);
243
+ return originalOpen.call(this, method, newUrl, ...args);
244
+ }
245
+ return originalOpen.call(this, method, url, ...args);
246
+ };
247
+
248
+ console.log("URL Fixer installed");
249
+ })();
250
+ </script>
251
+ """)
252
+
253
  # Mount the static directory for other static files
254
  if static_path.exists():
255
  app.mount("/static", StaticFiles(directory=str(static_path)), name="static")
 
257
  # Catch-all route for client-side routing in the React app
258
  @app.get("/{full_path:path}")
259
  async def catch_all(full_path: str, request: Request):
260
+ # Skip API paths and redirect them to the backend
261
+ if full_path.startswith("api/") or full_path == "docs" or full_path == "openapi.json":
262
+ if backend_available:
263
+ # Use the backend.app.main module's routes
264
+ return backend.app.main.app.get(full_path)
265
+ else:
266
+ return {"error": "Backend API not available"}
267
+
268
  # Skip static file paths
269
  if full_path.startswith("static/") or full_path.startswith("assets/"):
270
  raise HTTPException(status_code=404, detail="Not found")