Spaces:
Sleeping
Sleeping
import httpx | |
from fastapi import FastAPI, Request | |
from fastapi.responses import StreamingResponse, JSONResponse | |
from fastapi.middleware.cors import CORSMiddleware | |
import uvicorn | |
import subprocess | |
import signal | |
app = FastAPI() | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=["*"], | |
allow_credentials=True, | |
allow_methods=["*"], | |
allow_headers=["*"], | |
) | |
PYTHON_PORT = 7860 | |
NODE_PORT = 4321 | |
NODE_SCRIPT_PATH = "build" | |
node_process = subprocess.Popen(["node", NODE_SCRIPT_PATH]) | |
def handle_sigterm(signum, frame): | |
print("Stopping Node.js server...") | |
node_process.terminate() | |
node_process.wait() | |
exit(0) | |
signal.signal(signal.SIGTERM, handle_sigterm) | |
def shutdown_event(): | |
print("Stopping Node.js server...") | |
node_process.terminate() | |
node_process.wait() | |
async def route_with_config(): | |
return JSONResponse(content={"one": "hello", "two": "from", "three": "Python"}) | |
async def proxy_to_node(request: Request): | |
client = httpx.AsyncClient() | |
# Preserve the full path including query parameters | |
full_path = request.url.path | |
if request.url.query: | |
full_path += f"?{request.url.query}" | |
url = f"http://localhost:{NODE_PORT}{full_path}" | |
headers = { | |
k: v | |
for k, v in request.headers.items() | |
if k.lower() not in ["host", "content-length"] | |
} | |
body = await request.body() | |
async with client: | |
response = await client.request( | |
method=request.method, url=url, headers=headers, content=body | |
) | |
return StreamingResponse( | |
response.iter_bytes(), | |
status_code=response.status_code, | |
headers=response.headers, | |
) | |
async def catch_all(request: Request, path: str): | |
return await proxy_to_node(request) | |
if __name__ == "__main__": | |
print( | |
f"Starting dual server. Python handles specific routes, Node handles the rest." | |
) | |
uvicorn.run(app, host="0.0.0.0", port=PYTHON_PORT) | |