mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 06:10:42 +00:00
fix(gateway): use secure dashboard links when TLS is enabled (#71499)
Fixes #71494. - Render Control UI links with https:// when gateway TLS is enabled. - Render websocket links with wss:// through the shared link resolver. - Add daemon status handoff coverage and TLS scheme docs. Co-authored-by: deepkilord <wang_hgang@msn.com>
This commit is contained in:
@@ -205,6 +205,7 @@ describe("gatherDaemonStatus", () => {
|
||||
}),
|
||||
);
|
||||
expect(status.gateway?.probeUrl).toBe("wss://127.0.0.1:19001");
|
||||
expect(status.gateway?.tlsEnabled).toBe(true);
|
||||
expect(status.rpc?.url).toBe("wss://127.0.0.1:19001");
|
||||
expect(status.rpc?.ok).toBe(true);
|
||||
expect(inspectGatewayRestart).not.toHaveBeenCalled();
|
||||
|
||||
@@ -43,6 +43,7 @@ type GatewayStatusSummary = {
|
||||
bindMode: GatewayBindMode;
|
||||
bindHost: string;
|
||||
customBindHost?: string;
|
||||
tlsEnabled?: boolean;
|
||||
port: number;
|
||||
portSource: "service args" | "env/config";
|
||||
probeUrl: string;
|
||||
@@ -284,7 +285,8 @@ async function resolveGatewayStatusSummary(params: {
|
||||
});
|
||||
const probeHost = pickProbeHostForBind(bindMode, tailnetIPv4, customBindHost);
|
||||
const probeUrlOverride = trimToUndefined(params.rpcUrlOverride) ?? null;
|
||||
const scheme = params.daemonCfg.gateway?.tls?.enabled === true ? "wss" : "ws";
|
||||
const tlsEnabled = params.daemonCfg.gateway?.tls?.enabled === true;
|
||||
const scheme = tlsEnabled ? "wss" : "ws";
|
||||
const probeUrl = probeUrlOverride ?? `${scheme}://${probeHost}:${daemonPort}`;
|
||||
let probeNote =
|
||||
!probeUrlOverride && bindMode === "lan"
|
||||
@@ -300,6 +302,7 @@ async function resolveGatewayStatusSummary(params: {
|
||||
bindMode,
|
||||
bindHost,
|
||||
customBindHost,
|
||||
...(tlsEnabled ? { tlsEnabled } : {}),
|
||||
port: daemonPort,
|
||||
portSource,
|
||||
probeUrl,
|
||||
|
||||
@@ -6,6 +6,9 @@ const runtime = vi.hoisted(() => ({
|
||||
log: vi.fn<(line: string) => void>(),
|
||||
error: vi.fn<(line: string) => void>(),
|
||||
}));
|
||||
const resolveControlUiLinksMock = vi.hoisted(() =>
|
||||
vi.fn((_opts?: unknown) => ({ httpUrl: "http://127.0.0.1:18789" })),
|
||||
);
|
||||
|
||||
vi.mock("../../runtime.js", () => ({
|
||||
defaultRuntime: runtime,
|
||||
@@ -21,7 +24,7 @@ vi.mock("../../terminal/theme.js", async () => {
|
||||
});
|
||||
|
||||
vi.mock("../../gateway/control-ui-links.js", () => ({
|
||||
resolveControlUiLinks: () => ({ httpUrl: "http://127.0.0.1:18789" }),
|
||||
resolveControlUiLinks: resolveControlUiLinksMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../daemon/inspect.js", () => ({
|
||||
@@ -73,6 +76,7 @@ describe("printDaemonStatus", () => {
|
||||
beforeEach(() => {
|
||||
runtime.log.mockReset();
|
||||
runtime.error.mockReset();
|
||||
resolveControlUiLinksMock.mockClear();
|
||||
});
|
||||
|
||||
it("prints stale gateway pid guidance when runtime does not own the listener", () => {
|
||||
@@ -152,4 +156,56 @@ describe("printDaemonStatus", () => {
|
||||
expect(runtime.log).toHaveBeenCalledWith(expect.stringContaining("Connectivity probe: ok"));
|
||||
expect(runtime.log).toHaveBeenCalledWith(expect.stringContaining("Capability: write-capable"));
|
||||
});
|
||||
|
||||
it("passes daemon TLS state to dashboard link rendering", () => {
|
||||
printDaemonStatus(
|
||||
{
|
||||
service: {
|
||||
label: "LaunchAgent",
|
||||
loaded: true,
|
||||
loadedText: "loaded",
|
||||
notLoadedText: "not loaded",
|
||||
runtime: { status: "running", pid: 8000 },
|
||||
},
|
||||
config: {
|
||||
cli: {
|
||||
path: "/tmp/openclaw-cli/openclaw.json",
|
||||
exists: true,
|
||||
valid: true,
|
||||
},
|
||||
daemon: {
|
||||
path: "/tmp/openclaw-daemon/openclaw.json",
|
||||
exists: true,
|
||||
valid: true,
|
||||
controlUi: { basePath: "/ui" },
|
||||
},
|
||||
mismatch: true,
|
||||
},
|
||||
gateway: {
|
||||
bindMode: "lan",
|
||||
bindHost: "0.0.0.0",
|
||||
port: 19001,
|
||||
portSource: "service args",
|
||||
probeUrl: "wss://127.0.0.1:19001",
|
||||
tlsEnabled: true,
|
||||
},
|
||||
rpc: {
|
||||
ok: true,
|
||||
kind: "connect",
|
||||
capability: "write_capable",
|
||||
url: "wss://127.0.0.1:19001",
|
||||
},
|
||||
extraServices: [],
|
||||
},
|
||||
{ json: false },
|
||||
);
|
||||
|
||||
expect(resolveControlUiLinksMock).toHaveBeenCalledWith({
|
||||
port: 19001,
|
||||
bind: "lan",
|
||||
customBindHost: undefined,
|
||||
basePath: "/ui",
|
||||
tlsEnabled: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -165,6 +165,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
bind: status.gateway.bindMode,
|
||||
customBindHost: status.gateway.customBindHost,
|
||||
basePath: status.config?.daemon?.controlUi?.basePath,
|
||||
tlsEnabled: status.gateway.tlsEnabled === true,
|
||||
});
|
||||
defaultRuntime.log(`${label("Dashboard:")} ${infoText(links.httpUrl)}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user