fix: DirectTerminal WebSocket URL behind reverse proxy

When the AO dashboard is served behind a reverse proxy (e.g. Caddy ->
FastAPI -> Next.js), the browser cannot reach the direct terminal
WebSocket server on port 14801. The connection attempt to
wss://hostname:14801/ws times out, leaving terminals stuck at
'Connecting...'.

Fix: detect when running on a standard port (443/80, indicating a
reverse proxy) and use a path-based WebSocket endpoint
(/ao-terminal-ws) instead of the direct port. This allows the proxy
to forward WebSocket connections to the terminal server.

Supports three modes:
1. NEXT_PUBLIC_TERMINAL_WS_PATH env var (explicit path override)
2. Auto-detect reverse proxy (standard port -> /ao-terminal-ws)
3. Direct port access (dev mode, non-standard port -> :14801)
This commit is contained in:
Prateek 2026-03-07 20:28:00 +05:30
parent 8801502871
commit 309bfbbc19
1 changed files with 15 additions and 2 deletions

View File

@ -184,10 +184,23 @@ export function DirectTerminal({
fit.fit();
// WebSocket URL (stable across reconnects)
// When accessed via reverse proxy (HTTPS on standard port), use path-based
// WebSocket endpoint instead of direct port access.
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
const hostname = window.location.hostname;
const port = process.env.NEXT_PUBLIC_DIRECT_TERMINAL_PORT ?? "14801";
const wsUrl = `${protocol}//${hostname}:${port}/ws?session=${encodeURIComponent(sessionId)}`;
const proxyWsPath = process.env.NEXT_PUBLIC_TERMINAL_WS_PATH;
let wsUrl: string;
if (proxyWsPath) {
// Path-based proxy (e.g. /ao-terminal-ws)
wsUrl = `${protocol}//${hostname}${proxyWsPath}?session=${encodeURIComponent(sessionId)}`;
} else if (window.location.port === "" || window.location.port === "443" || window.location.port === "80") {
// Behind reverse proxy on standard port — use path-based endpoint
wsUrl = `${protocol}//${hostname}/ao-terminal-ws?session=${encodeURIComponent(sessionId)}`;
} else {
// Direct access (dev mode) — use direct port
const port = process.env.NEXT_PUBLIC_DIRECT_TERMINAL_PORT ?? "14801";
wsUrl = `${protocol}//${hostname}:${port}/ws?session=${encodeURIComponent(sessionId)}`;
}
// ── Preserve selection while terminal receives output ────────
// xterm.js clears the selection on every terminal.write(). We