Files
UNITRONIX ce988724c1 fix(console): share one WebSocket upgrade dispatcher (#295)
Collapse 11 per-service upgrade listeners into wsUpgradeRouter so Node no longer emits a false MaxListenersExceededWarning at panel startup.
2026-07-22 18:21:50 +02:00

85 lines
3.0 KiB
JavaScript

/**
* MeshCentral .ashx WebSocket proxy — panel HTTPS → Go API listener.
* MeshAgent connects to wss://panel:5443/agent.ashx (no panel session; binary auth on Go).
*/
const WebSocket = require('ws');
const config = require('../config/config');
const { enforceOrigin } = require('../middleware/wsOrigin');
const { registerUpgradeHandler } = require('./wsUpgradeRouter');
const MESH_PATHS = new Set([
'/agent.ashx',
'/meshrelay.ashx',
'/control.ashx',
]);
function goWsBase() {
const base = config.betterdeskApiUrl || `http://127.0.0.1:${config.goApiPort || 21114}/api`;
return base.replace(/^http/, 'ws').replace(/\/api\/?$/, '');
}
function initMeshAshxProxy(server, sessionMiddleware) {
const wss = new WebSocket.Server({ noServer: true });
registerUpgradeHandler(
server,
(pathname) => MESH_PATHS.has(pathname),
(req, socket, head) => {
const url = new URL(req.url, `http://${req.headers.host}`);
const needsSession = url.pathname === '/control.ashx';
const label = `mesh-${url.pathname}`;
if (!enforceOrigin(req, socket, label)) return;
const connect = () => {
wss.handleUpgrade(req, socket, head, (browserWs) => {
const target = goWsBase() + url.pathname + (url.search || '');
const goWs = new WebSocket(target, {
headers: {
'x-forwarded-for': req.socket?.remoteAddress || '',
},
});
goWs.on('open', () => {
browserWs.on('message', (data, isBinary) => {
if (goWs.readyState === WebSocket.OPEN) {
goWs.send(data, { binary: isBinary });
}
});
goWs.on('message', (data, isBinary) => {
if (browserWs.readyState === WebSocket.OPEN) {
browserWs.send(data, { binary: isBinary });
}
});
});
goWs.on('error', (err) => {
console.warn('[mesh proxy]', url.pathname, err.message);
browserWs.close();
});
browserWs.on('close', () => goWs.close());
goWs.on('close', () => browserWs.close());
browserWs.on('error', () => goWs.close());
});
};
if (needsSession) {
sessionMiddleware(req, {}, () => {
if (!req.session || !req.session.userId) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
connect();
});
} else {
connect();
}
}
);
}
module.exports = { initMeshAshxProxy };