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

Implement advanced URL fixing by modifying JS files directly and handling login/signup requests more robustly

Browse files
Files changed (1) hide show
  1. app.py +243 -80
app.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import sys
3
  import shutil
4
  import logging
 
5
  from pathlib import Path
6
 
7
  # Set up logging
@@ -16,6 +17,48 @@ os.makedirs("./temp_audio", exist_ok=True)
16
  os.makedirs("./temp", exist_ok=True)
17
  os.makedirs("./static", exist_ok=True)
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  # Check for index.html and create a simple one if it doesn't exist
20
  static_path = Path("./static")
21
  index_path = static_path / "index.html"
@@ -87,12 +130,77 @@ 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
 
@@ -129,31 +237,60 @@ async def serve_assets(file_path: str):
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
@@ -161,25 +298,59 @@ async def login_proxy(request: Request):
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
@@ -187,69 +358,61 @@ async def signup_proxy(request: Request):
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")
 
2
  import sys
3
  import shutil
4
  import logging
5
+ import re
6
  from pathlib import Path
7
 
8
  # Set up logging
 
17
  os.makedirs("./temp", exist_ok=True)
18
  os.makedirs("./static", exist_ok=True)
19
 
20
+ # Function to fix localhost URLs in JavaScript files
21
+ def fix_js_files():
22
+ """Fix all JS files in the static directory to replace localhost:8000 with relative URLs"""
23
+ assets_dir = Path("./static/assets")
24
+ if not assets_dir.exists():
25
+ logger.warning(f"Assets directory not found at {assets_dir}")
26
+ return
27
+
28
+ logger.info(f"Searching for JS files in {assets_dir}")
29
+ js_files = list(assets_dir.glob("*.js"))
30
+ logger.info(f"Found {len(js_files)} JS files")
31
+
32
+ for js_file in js_files:
33
+ try:
34
+ logger.info(f"Processing {js_file}")
35
+ with open(js_file, "r", encoding="utf-8") as f:
36
+ content = f.read()
37
+
38
+ # Count occurrences before replacement
39
+ count_before = content.count("localhost:8000")
40
+ if count_before > 0:
41
+ logger.info(f"Found {count_before} instances of localhost:8000 in {js_file}")
42
+
43
+ # Replace localhost URLs with relative ones
44
+ modified_content = content.replace("http://localhost:8000", "")
45
+ modified_content = modified_content.replace("https://localhost:8000", "")
46
+
47
+ # Create a backup just in case
48
+ backup_file = js_file.with_suffix(".js.bak")
49
+ shutil.copy(js_file, backup_file)
50
+
51
+ # Write the modified content back
52
+ with open(js_file, "w", encoding="utf-8") as f:
53
+ f.write(modified_content)
54
+
55
+ logger.info(f"Fixed {count_before} localhost URLs in {js_file}")
56
+ except Exception as e:
57
+ logger.error(f"Error processing {js_file}: {str(e)}")
58
+
59
+ # Run the JS file fixer at startup
60
+ fix_js_files()
61
+
62
  # Check for index.html and create a simple one if it doesn't exist
63
  static_path = Path("./static")
64
  index_path = static_path / "index.html"
 
130
  logger.info("Root route accessed, serving index.html")
131
  html_content = get_index_html()
132
 
133
+ # Inject our URL rewriter scripts
134
+ script_tag = '''
135
+ <script>
136
+ (function() {
137
+ console.log("Advanced URL Fixer running...");
138
+
139
+ // Intercept all network requests
140
+ const originalFetch = window.fetch;
141
+ window.fetch = function(url, options) {
142
+ if (typeof url === 'string') {
143
+ // Rewrite localhost:8000
144
+ if (url.includes('localhost:8000')) {
145
+ url = url.replace('http://localhost:8000', '');
146
+ url = url.replace('https://localhost:8000', '');
147
+ console.log(`Rewriting URL from localhost:8000 to ${url}`);
148
+ }
149
+
150
+ // Handle relative URLs for API endpoints
151
+ if (url.startsWith('/')) {
152
+ if (!url.startsWith('/static/') && !url.startsWith('/assets/')) {
153
+ console.log(`Using relative URL: ${url}`);
154
+ }
155
+ }
156
+ }
157
+ return originalFetch(url, options);
158
+ };
159
+
160
+ // Override XMLHttpRequest
161
+ const originalOpen = XMLHttpRequest.prototype.open;
162
+ XMLHttpRequest.prototype.open = function(method, url, ...args) {
163
+ if (typeof url === 'string') {
164
+ // Rewrite localhost:8000
165
+ if (url.includes('localhost:8000')) {
166
+ url = url.replace('http://localhost:8000', '');
167
+ url = url.replace('https://localhost:8000', '');
168
+ console.log(`Rewriting XHR URL from localhost:8000 to ${url}`);
169
+ }
170
+ }
171
+ return originalOpen.call(this, method, url, ...args);
172
+ };
173
+
174
+ // Attempt to hook into axios if it's being used
175
+ if (window.axios) {
176
+ const originalAxiosGet = window.axios.get;
177
+ window.axios.get = function(url, config) {
178
+ if (typeof url === 'string' && url.includes('localhost:8000')) {
179
+ url = url.replace('http://localhost:8000', '');
180
+ console.log(`Rewriting axios URL from localhost:8000 to ${url}`);
181
+ }
182
+ return originalAxiosGet(url, config);
183
+ };
184
+
185
+ const originalAxiosPost = window.axios.post;
186
+ window.axios.post = function(url, data, config) {
187
+ if (typeof url === 'string' && url.includes('localhost:8000')) {
188
+ url = url.replace('http://localhost:8000', '');
189
+ console.log(`Rewriting axios POST URL from localhost:8000 to ${url}`);
190
+ }
191
+ return originalAxiosPost(url, data, config);
192
+ };
193
+ }
194
+
195
+ console.log("Advanced URL Fixer installed");
196
+ })();
197
+ </script>
198
+ '''
199
+
200
+ if '</body>' in html_content:
201
  html_content = html_content.replace('</body>', f'{script_tag}</body>')
202
+ else:
203
+ html_content = html_content + script_tag
204
 
205
  return HTMLResponse(content=html_content)
206
 
 
237
  # Special handlers for API routes that the React app calls directly
238
  @app.post("/login")
239
  async def login_proxy(request: Request):
240
+ logger.info("Received login request at /login endpoint")
241
  if backend_available:
 
242
  try:
243
+ # Read request body as bytes
244
+ body_bytes = await request.body()
 
 
 
 
245
 
246
+ # Try to parse as JSON
247
+ try:
248
+ from fastapi.encoders import jsonable_encoder
249
+ # Use backend login function directly
250
+ from backend.app.main import login
251
+
252
+ # Parse the request body
253
+ user_data = await request.json()
254
+ logger.info(f"Login request data: {user_data}")
255
+
256
+ # Call the backend function
257
+ result = await login(request)
258
+ return result
259
+ except Exception as json_error:
260
+ logger.error(f"Error parsing JSON in login request: {str(json_error)}")
261
+
262
+ # If JSON parsing fails, try using the raw request
263
+ try:
264
+ # Forward to the backend as a new request
265
+ from starlette.requests import Request as StarletteRequest
266
+
267
+ # Create a new scope
268
+ scope = {
269
+ "type": "http",
270
+ "method": "POST",
271
+ "path": "/login",
272
+ "headers": [[k.lower().encode(), v.encode()] for k, v in request.headers.items()],
273
+ }
274
+
275
+ # Create a new request with the same body
276
+ from starlette.datastructures import Headers
277
+ new_req = StarletteRequest(scope=scope, receive=lambda: {"type": "http.request", "body": body_bytes})
278
+
279
+ # Call backend login function
280
+ from backend.app.main import login
281
+ result = await login(new_req)
282
+ return result
283
+ except Exception as raw_error:
284
+ logger.error(f"Error forwarding raw request to login: {str(raw_error)}")
285
+ raise HTTPException(status_code=500, detail=f"Login processing error: {str(raw_error)}")
286
  except Exception as e:
287
+ logger.error(f"General error in login_proxy: {str(e)}")
288
  return JSONResponse(
289
  content={"error": "Login failed", "message": str(e)},
290
  status_code=500
291
  )
292
  else:
293
+ logger.error("Backend not available for login")
294
  return JSONResponse(
295
  content={"error": "Backend API not available for login"},
296
  status_code=503
 
298
 
299
  @app.post("/signup")
300
  async def signup_proxy(request: Request):
301
+ logger.info("Received signup request at /signup endpoint")
302
  if backend_available:
303
  try:
304
+ # Read request body as bytes
305
+ body_bytes = await request.body()
 
 
 
306
 
307
+ # Try to parse as JSON
308
+ try:
309
+ from fastapi.encoders import jsonable_encoder
310
+ # Use backend signup function directly
311
+ from backend.app.main import signup
312
+
313
+ # Parse the request body
314
+ user_data = await request.json()
315
+ logger.info(f"Signup request data: {user_data}")
316
+
317
+ # Call the backend function
318
+ result = await signup(user_data)
319
+ return result
320
+ except Exception as json_error:
321
+ logger.error(f"Error parsing JSON in signup request: {str(json_error)}")
322
+
323
+ # If JSON parsing fails, try using the raw request
324
+ try:
325
+ # Forward to the backend as a new request
326
+ from starlette.requests import Request as StarletteRequest
327
+
328
+ # Create a new scope
329
+ scope = {
330
+ "type": "http",
331
+ "method": "POST",
332
+ "path": "/signup",
333
+ "headers": [[k.lower().encode(), v.encode()] for k, v in request.headers.items()],
334
+ }
335
+
336
+ # Create a new request with the same body
337
+ new_req = StarletteRequest(scope=scope, receive=lambda: {"type": "http.request", "body": body_bytes})
338
+
339
+ # Call backend signup function
340
+ from backend.app.main import signup
341
+ result = await signup(new_req)
342
+ return result
343
+ except Exception as raw_error:
344
+ logger.error(f"Error forwarding raw request to signup: {str(raw_error)}")
345
+ raise HTTPException(status_code=500, detail=f"Signup processing error: {str(raw_error)}")
346
  except Exception as e:
347
+ logger.error(f"General error in signup_proxy: {str(e)}")
348
  return JSONResponse(
349
  content={"error": "Signup failed", "message": str(e)},
350
  status_code=500
351
  )
352
  else:
353
+ logger.error("Backend not available for signup")
354
  return JSONResponse(
355
  content={"error": "Backend API not available for signup"},
356
  status_code=503
 
358
 
359
  @app.post("/token")
360
  async def token_proxy(request: Request):
361
+ logger.info("Received token request at /token endpoint")
362
  if backend_available:
363
  try:
364
+ # Read request body as bytes
365
+ body_bytes = await request.body()
 
 
 
366
 
367
+ # Try to get form data
368
+ try:
369
+ form_data = await request.form()
370
+
371
+ # Import the token handler
372
+ from backend.app.main import login_for_access_token
373
+
374
+ # Call the backend function
375
+ result = await login_for_access_token(form_data)
376
+ return result
377
+ except Exception as form_error:
378
+ logger.error(f"Error processing form data in token request: {str(form_error)}")
379
+
380
+ # If form parsing fails, try forwarding the raw request
381
+ try:
382
+ # Forward to the backend as a new request
383
+ from starlette.requests import Request as StarletteRequest
384
+
385
+ # Create a new scope
386
+ scope = {
387
+ "type": "http",
388
+ "method": "POST",
389
+ "path": "/token",
390
+ "headers": [[k.lower().encode(), v.encode()] for k, v in request.headers.items()],
391
+ }
392
+
393
+ # Create a new request with the same body
394
+ new_req = StarletteRequest(scope=scope, receive=lambda: {"type": "http.request", "body": body_bytes})
395
+
396
+ # Call backend token function
397
+ from backend.app.main import login_for_access_token
398
+ result = await login_for_access_token(new_req)
399
+ return result
400
+ except Exception as raw_error:
401
+ logger.error(f"Error forwarding raw request to token: {str(raw_error)}")
402
+ raise HTTPException(status_code=500, detail=f"Token processing error: {str(raw_error)}")
403
  except Exception as e:
404
+ logger.error(f"General error in token_proxy: {str(e)}")
405
  return JSONResponse(
406
  content={"error": "Token request failed", "message": str(e)},
407
  status_code=500
408
  )
409
  else:
410
+ logger.error("Backend not available for token request")
411
  return JSONResponse(
412
  content={"error": "Backend API not available for token request"},
413
  status_code=503
414
  )
415
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  # Mount the static directory for other static files
417
  if static_path.exists():
418
  app.mount("/static", StaticFiles(directory=str(static_path)), name="static")