Ubuntu / app.py
userrein's picture
Update app.py
16ce1dc verified
Raw History Blame Contribute Delete
2.61 kB
from fastapi import FastAPI, WebSocket
from fastapi.responses import PlainTextResponse
import asyncio
import os
import pty
import subprocess
app = FastAPI()
@app.get("/", response_class=PlainTextResponse)
async def root():
return "Bash WebSocket Terminal OK"
@app.get("/health", response_class=PlainTextResponse)
async def health():
return "OK"
@app.websocket("/terminals/websocket/{terminal_id}")
async def terminal(websocket: WebSocket, terminal_id: str):
await websocket.accept()
print("CONNECTED:", terminal_id, flush=True)
master, slave = pty.openpty()
process = subprocess.Popen(
["/bin/bash", "--noprofile", "--norc", "-i"],
stdin=slave,
stdout=slave,
stderr=slave,
start_new_session=True
)
os.close(slave)
loop = asyncio.get_running_loop()
async def bash_to_websocket():
while process.poll() is None:
try:
data = await loop.run_in_executor(
None,
os.read,
master,
8192
)
if not data:
break
output = data.decode(
"utf-8",
errors="replace"
)
print(
"BASH OUTPUT:",
repr(output),
flush=True
)
await websocket.send_text(output)
except Exception as e:
print(
"OUTPUT ERROR:",
repr(e),
flush=True
)
break
output_task = asyncio.create_task(
bash_to_websocket()
)
try:
while True:
data = await websocket.receive_text()
print(
"TERMUX INPUT:",
repr(data),
flush=True
)
os.write(
master,
data.encode("utf-8")
)
except Exception as e:
print(
"WEBSOCKET:",
repr(e),
flush=True
)
finally:
output_task.cancel()
try:
process.terminate()
except:
pass
try:
os.close(master)
except:
pass
print(
"DISCONNECTED:",
terminal_id,
flush=True
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(
app,
host="0.0.0.0",
port=7860
)