feat: serve plugin http and websockets from one mount instead of ports

This commit is contained in:
LukeGus committed 2026-09-22 16:39:41 -05:00
1 parent c496a093ca
commit 8431570ff7
102 files changed
+2894 -2308

No files matched your search

@@ -285,11 +285,13 @@ export const GuacamoleDisplay = forwardRef<
let wsBase: string | null;
if (isElectron()) {
// includeJwt stays off: a display authenticates with the encrypted
// connection token in the query, not a session.
const target = await buildOriginWsUrl({
origin,
localPort: 30008,
localPath: "/guacamole/websocket/",
remotePath: "/guacamole/websocket/",
localPort: 30001,
localPath: "/plugin-ws/remote-desktop/display",
remotePath: "/plugin-ws/remote-desktop/display",
includeJwt: false,
});
if (!target) {
@@ -299,7 +301,6 @@ export const GuacamoleDisplay = forwardRef<
wsBase = target.url;
} else {
wsBase = buildGuacamoleWebSocketBaseUrl({
isDev,
isElectronApp: false,
isEmbeddedApp: false,
basePath: getBasePath(),
@@ -174,17 +174,20 @@ export async function getGuacamoleToken(
try {
const guacParams = toGuacamoleParams(request.guacamoleConfig);
const response = await guacamoleApi(origin).post("/guacamole/token", {
type: request.protocol,
hostname: request.hostname,
port: request.port,
username: request.username,
password: request.password,
domain: request.domain,
security: request.security,
"ignore-cert": request.ignoreCert,
...guacParams,
});
const response = await guacamoleApi(origin).post(
"/plugin-api/remote-desktop/token",
{
type: request.protocol,
hostname: request.hostname,
port: request.port,
username: request.username,
password: request.password,
domain: request.domain,
security: request.security,
"ignore-cert": request.ignoreCert,
...guacParams,
},
);
return response.data;
} catch (error) {
throw handleApiError(error, "get guacamole token");
@@ -214,7 +217,7 @@ export async function getGuacamoleTokenFromHost(
}
const targetHostId = remoteHostId ?? hostId;
const response = await guacamoleApi(origin).post(
`/guacamole/connect-host/${targetHostId}`,
`/plugin-api/remote-desktop/connect-host/${targetHostId}`,
{
...(protocol ? { protocol } : {}),
...(promptedCredentials?.username
@@ -237,7 +240,9 @@ export async function getGuacamoleTokenFromHost(
export async function getGuacdStatus(origin: ConnectionOrigin): Promise<{
guacd: { status: string };
}> {
const response = await guacamoleApi(origin).get("/guacamole/status");
const response = await guacamoleApi(origin).get(
"/plugin-api/remote-desktop/status",
);
return response.data;
}
@@ -247,7 +252,7 @@ export async function getGuacamoleConnectionId(
signal?: AbortSignal,
): Promise<string | null> {
const response = await guacamoleApi(origin).get(
`/guacamole/connection/${encodeURIComponent(connectId)}`,
`/plugin-api/remote-desktop/connection/${encodeURIComponent(connectId)}`,
{ signal },
);
return response.data.guacamoleConnectionId ?? null;
@@ -1,31 +1,39 @@
/**
* Where the Guacamole display socket lives.
*
* One path in every deployment: the plugin serves it at
* /plugin-ws/remote-desktop/display on the main backend, so there is no
* guacamole port and no separate nginx block any more. Electron with a remote
* server is the only case that targets a different host.
*/
export function buildGuacamoleWebSocketBaseUrl({
isDev,
isElectronApp,
isEmbeddedApp,
configuredServerUrl,
basePath,
location,
}: {
isDev: boolean;
isDev?: boolean;
isElectronApp: boolean;
isEmbeddedApp: boolean;
configuredServerUrl?: string;
basePath: string;
location: Pick<Location, "protocol" | "host">;
}) {
if (isDev) return "ws://localhost:30008";
if (isElectronApp) {
if (isEmbeddedApp || !configuredServerUrl) return "ws://127.0.0.1:30008";
const route = "/plugin-ws/remote-desktop/display";
if (isElectronApp && !isEmbeddedApp && configuredServerUrl) {
const wsProtocol = configuredServerUrl.startsWith("https://")
? "wss://"
: "ws://";
const wsHost = configuredServerUrl
.replace(/^https?:\/\//, "")
.replace(/\/$/, "");
return `${wsProtocol}${wsHost}/guacamole/websocket/`;
return `${wsProtocol}${wsHost}${route}`;
}
if (isElectronApp) return `ws://127.0.0.1:30001${route}`;
const wsProtocol = location.protocol === "https:" ? "wss" : "ws";
return `${wsProtocol}://${location.host}${basePath}/guacamole/websocket/`;
return `${wsProtocol}://${location.host}${basePath}${route}`;
}