diff --git a/striker-ui-api/src/index.ts b/striker-ui-api/src/index.ts index 8cfe2903..81eb71cc 100644 --- a/striker-ui-api/src/index.ts +++ b/striker-ui-api/src/index.ts @@ -3,12 +3,13 @@ import { getgid, getuid, setgid, setuid } from 'process'; import { PGID, PUID, PORT, ECODE_DROP_PRIVILEGES } from './lib/consts'; import app from './app'; +import { proxyServerVncUpgrade } from './middlewares'; import { stderr, stdout } from './lib/shell'; (async () => { stdout(`Starting process with ownership ${getuid()}:${getgid()}`); - (await app).listen(PORT, () => { + const server = (await app).listen(PORT, () => { try { // Group must be set before user to avoid permission error. setgid(PGID); @@ -23,4 +24,6 @@ import { stderr, stdout } from './lib/shell'; stdout(`Listening on localhost:${PORT}.`); }); + + server.on('upgrade', proxyServerVncUpgrade); })(); diff --git a/striker-ui-api/src/lib/accessModule.ts b/striker-ui-api/src/lib/accessModule.ts index 8360deda..cebe8790 100644 --- a/striker-ui-api/src/lib/accessModule.ts +++ b/striker-ui-api/src/lib/accessModule.ts @@ -394,12 +394,12 @@ const getVncinfo = async (serverUuid: string): Promise => { } const [[vncinfo]] = rows; - const [domain, port] = vncinfo.split(':'); + const [domain, rPort] = vncinfo.split(':'); - const forwardPort = Number.parseInt(port); + const port = Number.parseInt(rPort); const protocol = 'ws'; - return { domain, forwardPort, protocol }; + return { domain, port, protocol }; }; export { diff --git a/striker-ui-api/src/middlewares/index.ts b/striker-ui-api/src/middlewares/index.ts index 2020c48d..6eef80f1 100644 --- a/striker-ui-api/src/middlewares/index.ts +++ b/striker-ui-api/src/middlewares/index.ts @@ -3,5 +3,6 @@ import session from './session'; export * from './assertAuthentication'; export * from './assertInit'; +export * from './proxyServerVnc'; export { passport, session }; diff --git a/striker-ui-api/src/middlewares/proxyServerVnc.ts b/striker-ui-api/src/middlewares/proxyServerVnc.ts new file mode 100644 index 00000000..79e04705 --- /dev/null +++ b/striker-ui-api/src/middlewares/proxyServerVnc.ts @@ -0,0 +1,52 @@ +import { ServerResponse } from 'http'; +import { createProxyMiddleware } from 'http-proxy-middleware'; + +import { P_UUID } from '../lib/consts'; + +import { stderr, stdout } from '../lib/shell'; +import { getVncinfo } from '../lib/accessModule'; + +const WS_SVR_VNC_URL_PREFIX = '/ws/server/vnc'; + +export const proxyServerVnc = createProxyMiddleware({ + changeOrigin: true, + pathFilter: `${WS_SVR_VNC_URL_PREFIX}/*`, + router: async (request) => { + const { url = '' } = request; + + const serverUuid = url.replace( + new RegExp(`^${WS_SVR_VNC_URL_PREFIX}/(${P_UUID})`), + '$1', + ); + + stdout(`Got param [${serverUuid}] from [${url}]`); + + let domain: string; + let port: number; + let protocol: string; + + try { + ({ domain, port, protocol } = await getVncinfo(serverUuid)); + } catch (error) { + throw new Error( + `Failed to get server ${serverUuid} VNC info; CAUSE: ${error}`, + ); + } + + return { host: domain, protocol, port }; + }, + on: { + error: (error, request, response) => { + stderr(String(error)); + + (response as ServerResponse).writeHead(404).end(); + }, + }, + ws: true, +}); + +export const proxyServerVncUpgrade = + proxyServerVnc.upgrade ?? + (() => { + stdout('No upgrade handler for server VNC connection(s).'); + }); diff --git a/striker-ui-api/src/types/ApiServer.d.ts b/striker-ui-api/src/types/ApiServer.d.ts index 7b0c789a..c7ba1850 100644 --- a/striker-ui-api/src/types/ApiServer.d.ts +++ b/striker-ui-api/src/types/ApiServer.d.ts @@ -23,6 +23,6 @@ type ServerDetailScreenshot = { type ServerDetailVncInfo = { domain: string; - forwardPort: number; + port: number; protocol: string; };