fix: use bridge canvas host for nodes
This commit is contained in:
@@ -34,7 +34,9 @@ describe("canvas host", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
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();
|
const html = await res.text();
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
expect(html).toContain("Interactive test page");
|
expect(html).toContain("Interactive test page");
|
||||||
@@ -111,7 +113,9 @@ describe("canvas host", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
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();
|
const html = await res.text();
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
expect(html).toContain("v1");
|
expect(html).toContain("v1");
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ export async function startCanvasHost(
|
|||||||
const handler = await createCanvasHostHandler({
|
const handler = await createCanvasHostHandler({
|
||||||
runtime: opts.runtime,
|
runtime: opts.runtime,
|
||||||
rootDir: opts.rootDir,
|
rootDir: opts.rootDir,
|
||||||
basePath: "/",
|
basePath: CANVAS_HOST_PATH,
|
||||||
allowInTests: opts.allowInTests,
|
allowInTests: opts.allowInTests,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1584,7 +1584,7 @@ describe("gateway server", () => {
|
|||||||
await new Promise<void>((resolve) => ws.once("open", resolve));
|
await new Promise<void>((resolve) => ws.once("open", resolve));
|
||||||
|
|
||||||
const hello = await connectOk(ws, { token: "secret" });
|
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();
|
ws.close();
|
||||||
await server.close();
|
await server.close();
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ import {
|
|||||||
} from "../canvas-host/a2ui.js";
|
} from "../canvas-host/a2ui.js";
|
||||||
import {
|
import {
|
||||||
type CanvasHostHandler,
|
type CanvasHostHandler,
|
||||||
|
type CanvasHostServer,
|
||||||
createCanvasHostHandler,
|
createCanvasHostHandler,
|
||||||
|
startCanvasHost,
|
||||||
} from "../canvas-host/server.js";
|
} from "../canvas-host/server.js";
|
||||||
import { createDefaultDeps } from "../cli/deps.js";
|
import { createDefaultDeps } from "../cli/deps.js";
|
||||||
import { agentCommand } from "../commands/agent.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(
|
function deriveCanvasHostUrl(
|
||||||
req: IncomingMessage | undefined,
|
req: IncomingMessage | undefined,
|
||||||
canvasPort: number | undefined,
|
canvasPort: number | undefined,
|
||||||
|
hostOverride?: string,
|
||||||
) {
|
) {
|
||||||
if (!req || !canvasPort) return undefined;
|
if (!req || !canvasPort) return undefined;
|
||||||
const hostHeader = req.headers.host?.trim();
|
const hostHeader = req.headers.host?.trim();
|
||||||
@@ -406,8 +409,9 @@ function deriveCanvasHostUrl(
|
|||||||
: undefined;
|
: undefined;
|
||||||
const scheme = forwardedProto === "https" ? "https" : "http";
|
const scheme = forwardedProto === "https" ? "https" : "http";
|
||||||
|
|
||||||
let host = "";
|
let host = (hostOverride ?? "").trim();
|
||||||
if (hostHeader) {
|
if (host === "0.0.0.0" || host === "::") host = "";
|
||||||
|
if (!host && hostHeader) {
|
||||||
try {
|
try {
|
||||||
const parsed = new URL(`http://${hostHeader}`);
|
const parsed = new URL(`http://${hostHeader}`);
|
||||||
host = parsed.hostname;
|
host = parsed.hostname;
|
||||||
@@ -1025,6 +1029,7 @@ export async function startGatewayServer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let canvasHost: CanvasHostHandler | null = null;
|
let canvasHost: CanvasHostHandler | null = null;
|
||||||
|
let canvasHostServer: CanvasHostServer | null = null;
|
||||||
if (canvasHostEnabled) {
|
if (canvasHostEnabled) {
|
||||||
try {
|
try {
|
||||||
const handler = await createCanvasHostHandler({
|
const handler = await createCanvasHostHandler({
|
||||||
@@ -1318,6 +1323,31 @@ export async function startGatewayServer(
|
|||||||
return "0.0.0.0";
|
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 bridgeSubscribe = (nodeId: string, sessionKey: string) => {
|
||||||
const normalizedNodeId = nodeId.trim();
|
const normalizedNodeId = nodeId.trim();
|
||||||
const normalizedSessionKey = sessionKey.trim();
|
const normalizedSessionKey = sessionKey.trim();
|
||||||
@@ -2079,11 +2109,7 @@ export async function startGatewayServer(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const machineDisplayName = await getMachineDisplayName();
|
const machineDisplayName = await getMachineDisplayName();
|
||||||
const bridgeHostIsLoopback = bridgeHost ? isLoopbackHost(bridgeHost) : false;
|
const canvasHostPortForBridge = canvasHostServer?.port;
|
||||||
const canvasHostPortForBridge =
|
|
||||||
canvasHost && (!isLoopbackHost(bindHost) || bridgeHostIsLoopback)
|
|
||||||
? port
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
if (bridgeEnabled && bridgePort > 0 && bridgeHost) {
|
if (bridgeEnabled && bridgePort > 0 && bridgeHost) {
|
||||||
try {
|
try {
|
||||||
@@ -2381,9 +2407,15 @@ export async function startGatewayServer(
|
|||||||
const remoteAddr = (
|
const remoteAddr = (
|
||||||
socket as WebSocket & { _socket?: { remoteAddress?: string } }
|
socket as WebSocket & { _socket?: { remoteAddress?: string } }
|
||||||
)._socket?.remoteAddress;
|
)._socket?.remoteAddress;
|
||||||
|
const canvasHostPortForWs = canvasHostServer?.port ?? (canvasHost ? port : undefined);
|
||||||
|
const canvasHostOverride =
|
||||||
|
bridgeHost && bridgeHost !== "0.0.0.0" && bridgeHost !== "::"
|
||||||
|
? bridgeHost
|
||||||
|
: undefined;
|
||||||
const canvasHostUrl = deriveCanvasHostUrl(
|
const canvasHostUrl = deriveCanvasHostUrl(
|
||||||
req,
|
req,
|
||||||
canvasHost ? port : undefined,
|
canvasHostPortForWs,
|
||||||
|
canvasHostServer ? canvasHostOverride : undefined,
|
||||||
);
|
);
|
||||||
logWs("in", "open", { connId, remoteAddr });
|
logWs("in", "open", { connId, remoteAddr });
|
||||||
const isWebchatConnect = (params: ConnectParams | null | undefined) =>
|
const isWebchatConnect = (params: ConnectParams | null | undefined) =>
|
||||||
@@ -4398,6 +4430,13 @@ export async function startGatewayServer(
|
|||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (canvasHostServer) {
|
||||||
|
try {
|
||||||
|
await canvasHostServer.close();
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
if (bridge) {
|
if (bridge) {
|
||||||
try {
|
try {
|
||||||
await bridge.close();
|
await bridge.close();
|
||||||
|
|||||||
Reference in New Issue
Block a user