mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-31 03:41:51 +00:00
fix(gateway): keep status helpers resilient to netif failures
This commit is contained in:
@@ -215,6 +215,36 @@ describe("gatherDaemonStatus", () => {
|
||||
expect(status.rpc?.url).toBe("wss://override.example:18790");
|
||||
});
|
||||
|
||||
it("uses fallback network details when interface discovery throws during status inspection", async () => {
|
||||
daemonLoadedConfig = {
|
||||
gateway: {
|
||||
bind: "tailnet",
|
||||
tls: { enabled: true },
|
||||
auth: { token: "daemon-token" },
|
||||
},
|
||||
};
|
||||
resolveGatewayBindHost.mockImplementationOnce(async () => {
|
||||
throw new Error("uv_interface_addresses failed");
|
||||
});
|
||||
pickPrimaryTailnetIPv4.mockImplementationOnce(() => {
|
||||
throw new Error("uv_interface_addresses failed");
|
||||
});
|
||||
|
||||
const status = await gatherDaemonStatus({
|
||||
rpc: {},
|
||||
probe: true,
|
||||
deep: false,
|
||||
});
|
||||
|
||||
expect(status.gateway).toMatchObject({
|
||||
bindMode: "tailnet",
|
||||
bindHost: "127.0.0.1",
|
||||
probeUrl: "wss://127.0.0.1:19001",
|
||||
});
|
||||
expect(status.gateway?.probeNote).toContain("interface discovery failed");
|
||||
expect(status.gateway?.probeNote).toContain("tailnet addresses");
|
||||
});
|
||||
|
||||
it("reuses command environment when reading runtime status", async () => {
|
||||
serviceReadCommand.mockResolvedValueOnce({
|
||||
programArguments: ["/bin/node", "cli", "gateway", "--port", "19001"],
|
||||
|
||||
@@ -74,6 +74,37 @@ type ResolvedGatewayStatus = {
|
||||
probeUrlOverride: string | null;
|
||||
};
|
||||
|
||||
function summarizeDisplayNetworkError(error: unknown): string {
|
||||
if (error instanceof Error) {
|
||||
const message = error.message.trim();
|
||||
if (message) {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
return "network interface discovery failed";
|
||||
}
|
||||
|
||||
function fallbackBindHostForStatus(bindMode: GatewayBindMode, customBindHost?: string): string {
|
||||
if (bindMode === "lan") {
|
||||
return "0.0.0.0";
|
||||
}
|
||||
if (bindMode === "custom") {
|
||||
return customBindHost?.trim() || "0.0.0.0";
|
||||
}
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
function appendProbeNote(
|
||||
existing: string | undefined,
|
||||
extra: string | undefined,
|
||||
): string | undefined {
|
||||
const values = [existing, extra].filter((value): value is string => Boolean(value?.trim()));
|
||||
if (values.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return [...new Set(values)].join(" ");
|
||||
}
|
||||
|
||||
export type DaemonStatus = {
|
||||
service: {
|
||||
label: string;
|
||||
@@ -201,18 +232,34 @@ async function resolveGatewayStatusSummary(params: {
|
||||
: "env/config";
|
||||
const bindMode: GatewayBindMode = params.daemonCfg.gateway?.bind ?? "loopback";
|
||||
const customBindHost = params.daemonCfg.gateway?.customBindHost;
|
||||
const bindHost = await resolveGatewayBindHost(bindMode, customBindHost);
|
||||
const tailnetIPv4 = pickPrimaryTailnetIPv4();
|
||||
let bindHost: string;
|
||||
let networkWarning: string | undefined;
|
||||
try {
|
||||
bindHost = await resolveGatewayBindHost(bindMode, customBindHost);
|
||||
} catch (error) {
|
||||
bindHost = fallbackBindHostForStatus(bindMode, customBindHost);
|
||||
networkWarning = `Status is using fallback network details because interface discovery failed: ${summarizeDisplayNetworkError(error)}.`;
|
||||
}
|
||||
let tailnetIPv4: string | undefined;
|
||||
try {
|
||||
tailnetIPv4 = pickPrimaryTailnetIPv4();
|
||||
} catch (error) {
|
||||
networkWarning = appendProbeNote(
|
||||
networkWarning,
|
||||
`Status could not inspect tailnet addresses: ${summarizeDisplayNetworkError(error)}.`,
|
||||
);
|
||||
}
|
||||
const probeHost = pickProbeHostForBind(bindMode, tailnetIPv4, customBindHost);
|
||||
const probeUrlOverride = trimToUndefined(params.rpcUrlOverride) ?? null;
|
||||
const scheme = params.daemonCfg.gateway?.tls?.enabled === true ? "wss" : "ws";
|
||||
const probeUrl = probeUrlOverride ?? `${scheme}://${probeHost}:${daemonPort}`;
|
||||
const probeNote =
|
||||
let probeNote =
|
||||
!probeUrlOverride && bindMode === "lan"
|
||||
? `bind=lan listens on 0.0.0.0 (all interfaces); probing via ${probeHost}.`
|
||||
: !probeUrlOverride && bindMode === "loopback"
|
||||
? "Loopback-only gateway; only local clients can connect."
|
||||
: undefined;
|
||||
probeNote = appendProbeNote(probeNote, networkWarning);
|
||||
|
||||
return {
|
||||
gateway: {
|
||||
|
||||
Reference in New Issue
Block a user