fix(run): forward text-frame keystrokes to pty and fix ws-pty upgrade dispatch
xterm.js's onData hands the browser a plain string, and WebSocket.send(string)
always emits a TEXT frame — pty-attach.js only forwarded BINARY frames to
pty.write(), so every keystroke was silently dropped as an unparseable JSON
control message. Now any non-control text frame reaches the pty.
Deeper root cause of the terminal never accepting input at all: the /ws
WebSocketServer used the {server, path} shorthand, whose own internal
upgrade listener calls handleUpgrade() for every upgrade on the shared
http.Server and aborts with 400 on a path mismatch — killing /ws-pty/*
upgrades before the PTY server's own listener ever ran. Switched /ws to
noServer + a manual path-checked dispatch, matching /ws-pty's pattern.
This commit is contained in:
+16
-4
@@ -9,11 +9,15 @@ const { isHostAllowed, isWebSocketAuthorized } = require("./lib/security");
|
||||
let wss = null;
|
||||
|
||||
function initWebSocket(server) {
|
||||
// Express middleware doesn't run on WS upgrades, so enforce the same Host
|
||||
// allowlist (anti DNS-rebinding) and optional token here (GHSA-gr74-4xfh-6jw9).
|
||||
// `noServer: true` + a manual, path-checked `server.on("upgrade", ...)`
|
||||
// rather than the `{server, path}` shorthand: that shorthand's own
|
||||
// internal upgrade listener calls `handleUpgrade` for EVERY upgrade on the
|
||||
// shared http.Server (path filtering happens inside `handleUpgrade`,
|
||||
// which `abortHandshake`s with 400 on a mismatch) — so it was answering,
|
||||
// and killing, `/ws-pty/*` upgrades before the PTY server's own listener
|
||||
// (registered below by `initPtyWebSocket`) ever got a chance to run.
|
||||
wss = new WebSocketServer({
|
||||
server,
|
||||
path: "/ws",
|
||||
noServer: true,
|
||||
maxPayload: 64 * 1024,
|
||||
verifyClient(info, done) {
|
||||
if (!isHostAllowed(info.req.headers.host)) return done(false, 403, "host not allowed");
|
||||
@@ -22,6 +26,14 @@ function initWebSocket(server) {
|
||||
},
|
||||
});
|
||||
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
const url = new URL(req.url, "http://localhost");
|
||||
if (url.pathname !== "/ws") return; // not ours — `/ws-pty/*` handles its own path.
|
||||
wss.handleUpgrade(req, socket, head, (ws) => {
|
||||
wss.emit("connection", ws, req);
|
||||
});
|
||||
});
|
||||
|
||||
wss.on("connection", (ws) => {
|
||||
ws.isAlive = true;
|
||||
ws.on("pong", () => {
|
||||
|
||||
Reference in New Issue
Block a user