fix: use bridge canvas host for nodes

This commit is contained in:
Peter Steinberger
2025-12-20 22:24:59 +01:00
parent e53442d983
commit 6a30452b4a
4 changed files with 55 additions and 12 deletions

View File

@@ -34,7 +34,9 @@ describe("canvas host", () => {
});
try {
const res = await fetch(`http://127.0.0.1:${server.port}/`);
const res = await fetch(
`http://127.0.0.1:${server.port}${CANVAS_HOST_PATH}/`,
);
const html = await res.text();
expect(res.status).toBe(200);
expect(html).toContain("Interactive test page");
@@ -111,7 +113,9 @@ describe("canvas host", () => {
});
try {
const res = await fetch(`http://127.0.0.1:${server.port}/`);
const res = await fetch(
`http://127.0.0.1:${server.port}${CANVAS_HOST_PATH}/`,
);
const html = await res.text();
expect(res.status).toBe(200);
expect(html).toContain("v1");

View File

@@ -377,7 +377,7 @@ export async function startCanvasHost(
const handler = await createCanvasHostHandler({
runtime: opts.runtime,
rootDir: opts.rootDir,
basePath: "/",
basePath: CANVAS_HOST_PATH,
allowInTests: opts.allowInTests,
});

View File

@@ -1584,7 +1584,7 @@ describe("gateway server", () => {
await new Promise<void>((resolve) => ws.once("open", resolve));
const hello = await connectOk(ws, { token: "secret" });
expect(hello.canvasHostUrl).toBe(`http://100.64.0.1:${port}`);
expect(hello.canvasHostUrl).toBe(`http://100.64.0.1:18793`);
ws.close();
await server.close();

View File

@@ -24,7 +24,9 @@ import {
} from "../canvas-host/a2ui.js";
import {
type CanvasHostHandler,
type CanvasHostServer,
createCanvasHostHandler,
startCanvasHost,
} from "../canvas-host/server.js";
import { createDefaultDeps } from "../cli/deps.js";
import { agentCommand } from "../commands/agent.js";
@@ -395,6 +397,7 @@ const MAX_BUFFERED_BYTES = 1.5 * 1024 * 1024; // per-connection send buffer limi
function deriveCanvasHostUrl(
req: IncomingMessage | undefined,
canvasPort: number | undefined,
hostOverride?: string,
) {
if (!req || !canvasPort) return undefined;
const hostHeader = req.headers.host?.trim();
@@ -406,8 +409,9 @@ function deriveCanvasHostUrl(
: undefined;
const scheme = forwardedProto === "https" ? "https" : "http";
let host = "";
if (hostHeader) {
let host = (hostOverride ?? "").trim();
if (host === "0.0.0.0" || host === "::") host = "";
if (!host && hostHeader) {
try {
const parsed = new URL(`http://${hostHeader}`);
host = parsed.hostname;
@@ -1025,6 +1029,7 @@ export async function startGatewayServer(
}
let canvasHost: CanvasHostHandler | null = null;
let canvasHostServer: CanvasHostServer | null = null;
if (canvasHostEnabled) {
try {
const handler = await createCanvasHostHandler({
@@ -1318,6 +1323,31 @@ export async function startGatewayServer(
return "0.0.0.0";
})();
const canvasHostPort = (() => {
const configured = cfgAtStart.canvasHost?.port;
if (typeof configured === "number" && configured > 0) return configured;
return 18793;
})();
if (canvasHostEnabled && bridgeEnabled && bridgeHost) {
try {
const started = await startCanvasHost({
runtime: defaultRuntime,
rootDir: cfgAtStart.canvasHost?.root,
port: canvasHostPort,
listenHost: bridgeHost,
allowInTests: opts.allowCanvasHostInTests,
});
if (started.port > 0) {
canvasHostServer = started;
}
} catch (err) {
logWarn(
`gateway: canvas host failed to start on ${bridgeHost}:${canvasHostPort}: ${String(err)}`,
);
}
}
const bridgeSubscribe = (nodeId: string, sessionKey: string) => {
const normalizedNodeId = nodeId.trim();
const normalizedSessionKey = sessionKey.trim();
@@ -2079,11 +2109,7 @@ export async function startGatewayServer(
};
const machineDisplayName = await getMachineDisplayName();
const bridgeHostIsLoopback = bridgeHost ? isLoopbackHost(bridgeHost) : false;
const canvasHostPortForBridge =
canvasHost && (!isLoopbackHost(bindHost) || bridgeHostIsLoopback)
? port
: undefined;
const canvasHostPortForBridge = canvasHostServer?.port;
if (bridgeEnabled && bridgePort > 0 && bridgeHost) {
try {
@@ -2381,9 +2407,15 @@ export async function startGatewayServer(
const remoteAddr = (
socket as WebSocket & { _socket?: { remoteAddress?: string } }
)._socket?.remoteAddress;
const canvasHostPortForWs = canvasHostServer?.port ?? (canvasHost ? port : undefined);
const canvasHostOverride =
bridgeHost && bridgeHost !== "0.0.0.0" && bridgeHost !== "::"
? bridgeHost
: undefined;
const canvasHostUrl = deriveCanvasHostUrl(
req,
canvasHost ? port : undefined,
canvasHostPortForWs,
canvasHostServer ? canvasHostOverride : undefined,
);
logWs("in", "open", { connId, remoteAddr });
const isWebchatConnect = (params: ConnectParams | null | undefined) =>
@@ -4398,6 +4430,13 @@ export async function startGatewayServer(
/* ignore */
}
}
if (canvasHostServer) {
try {
await canvasHostServer.close();
} catch {
/* ignore */
}
}
if (bridge) {
try {
await bridge.close();