File size: 2,729 Bytes
277e435 01e96cb 46c75bc 277e435 46c75bc d24dec8 46c75bc 2c2ff35 9bf31c9 2c2ff35 66e5e1b 33341ab 66e5e1b 9bf31c9 2c2ff35 33341ab 2c2ff35 66e5e1b 2c2ff35 66e5e1b 33341ab 2c2ff35 be0aa6a 33341ab 2c2ff35 be0aa6a 2c2ff35 be0aa6a 33341ab be0aa6a 01e96cb be0aa6a 01e96cb 33341ab 01e96cb 33341ab be0aa6a 33341ab be0aa6a 46c75bc 66e5e1b d24dec8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | import uvicorn
from fastapi import FastAPI, Request, WebSocket
from fastapi.responses import HTMLResponse, StreamingResponse
import httpx
import asyncio
import websockets
app = FastAPI()
client = httpx.AsyncClient(timeout=None)
@app.get("/", response_class=HTMLResponse)
async def root():
return "<body style='background:#000;color:#0f0;text-align:center;padding-top:100px;font-family:monospace;'><h1>[ SYSTEM ACTIVE ]</h1><p>Path: /terminal</p></body>"
# PROXY HTTP (Aset Terminal)
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def proxy_http(request: Request, path: str):
if not path or path == "/": return await root()
target_url = f"http://127.0.0.1:8080/{path}"
headers = {k: v for k, v in request.headers.items() if k.lower() not in ["host", "origin"]}
headers["Host"] = "127.0.0.1:8080"
headers["Origin"] = "http://127.0.0.1:8080"
try:
req = client.build_request(method=request.method, url=target_url, headers=headers, params=request.query_params, content=await request.body())
resp = await client.send(req, stream=True)
return StreamingResponse(resp.aiter_raw(), status_code=resp.status_code, headers=dict(resp.headers))
except:
return HTMLResponse("Backend Offline", status_code=503)
# PROXY WEBSOCKET (Fix Reconnect & Cant Type)
@app.websocket("/{path:path}")
async def proxy_ws(websocket: WebSocket, path: str):
# Terima koneksi dengan subprotocol asli dari ttyd
subproto = websocket.headers.get("sec-websocket-protocol")
await websocket.accept(subprotocol=subproto)
target_ws_url = f"ws://127.0.0.1:8080/{path}"
try:
# KUNCI: Jangan pake extra_headers agar tidak Exit 1 di log
async with websockets.connect(
target_ws_url,
subprotocols=[subproto] if subproto else None,
ping_interval=None # Agar tidak gampang putus
) as target_ws:
async def forward(source, destination):
try:
while True:
if hasattr(source, 'receive_text'):
msg = await source.receive_text()
await destination.send(msg)
else:
msg = await source.recv()
await destination.send_text(msg)
except: pass
await asyncio.gather(forward(websocket, target_ws), forward(target_ws, websocket))
except Exception as e:
print(f"WS Error: {str(e)}")
finally:
try:
await websocket.close()
except: pass
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)
|