refactor(gateway): cache hook proxy config in runtime state

This commit is contained in:
Peter Steinberger
2026-03-12 21:43:36 +00:00
parent 1d986f1c01
commit 445ff0242e
5 changed files with 34 additions and 15 deletions

View File

@@ -80,6 +80,11 @@ type HookDispatchers = {
dispatchAgentHook: (value: HookAgentDispatchPayload) => string;
};
export type HookClientIpConfig = Readonly<{
trustedProxies?: string[];
allowRealIpFallback?: boolean;
}>;
function sendJson(res: ServerResponse, status: number, body: unknown) {
res.statusCode = status;
res.setHeader("Content-Type", "application/json; charset=utf-8");
@@ -352,10 +357,7 @@ export function createHooksRequestHandler(
bindHost: string;
port: number;
logHooks: SubsystemLogger;
getClientIpConfig?: () => {
trustedProxies?: string[];
allowRealIpFallback?: boolean;
};
getClientIpConfig?: () => HookClientIpConfig;
} & HookDispatchers,
): HooksRequestHandler {
const { getHooksConfig, logHooks, dispatchAgentHook, dispatchWakeHook, getClientIpConfig } = opts;

View File

@@ -22,9 +22,12 @@ import type { GatewayReloadPlan } from "./config-reload.js";
import { resolveHooksConfig } from "./hooks.js";
import { startBrowserControlServerIfEnabled } from "./server-browser.js";
import { buildGatewayCronService, type GatewayCronState } from "./server-cron.js";
import type { HookClientIpConfig } from "./server-http.js";
import { resolveHookClientIpConfig } from "./server/hooks.js";
type GatewayHotReloadState = {
hooksConfig: ReturnType<typeof resolveHooksConfig>;
hookClientIpConfig: HookClientIpConfig;
heartbeatRunner: HeartbeatRunner;
cronState: GatewayCronState;
browserControl: Awaited<ReturnType<typeof startBrowserControlServerIfEnabled>> | null;
@@ -64,6 +67,7 @@ export function createGatewayReloadHandlers(params: {
params.logHooks.warn(`hooks config reload failed: ${String(err)}`);
}
}
nextState.hookClientIpConfig = resolveHookClientIpConfig(nextConfig);
if (plan.restartHeartbeat) {
nextState.heartbeatRunner.updateConfig(nextConfig);

View File

@@ -23,7 +23,11 @@ import {
createToolEventRecipientRegistry,
} from "./server-chat.js";
import { MAX_PREAUTH_PAYLOAD_BYTES } from "./server-constants.js";
import { attachGatewayUpgradeHandler, createGatewayHttpServer } from "./server-http.js";
import {
attachGatewayUpgradeHandler,
createGatewayHttpServer,
type HookClientIpConfig,
} from "./server-http.js";
import type { DedupeEntry } from "./server-shared.js";
import { createGatewayHooksRequestHandler } from "./server/hooks.js";
import { listenGatewayHttpServer } from "./server/http-listen.js";
@@ -53,6 +57,7 @@ export async function createGatewayRuntimeState(params: {
rateLimiter?: AuthRateLimiter;
gatewayTls?: GatewayTlsRuntime;
hooksConfig: () => HooksConfigResolved | null;
getHookClientIpConfig: () => HookClientIpConfig;
pluginRegistry: PluginRegistry;
deps: CliDeps;
canvasRuntime: RuntimeEnv;
@@ -113,6 +118,7 @@ export async function createGatewayRuntimeState(params: {
const handleHooksRequest = createGatewayHooksRequestHandler({
deps: params.deps,
getHooksConfig: params.hooksConfig,
getClientIpConfig: params.getHookClientIpConfig,
bindHost: params.bindHost,
port: params.port,
logHooks: params.logHooks,

View File

@@ -107,6 +107,7 @@ import {
incrementPresenceVersion,
refreshGatewayHealthSnapshot,
} from "./server/health-state.js";
import { resolveHookClientIpConfig } from "./server/hooks.js";
import { createReadinessChecker } from "./server/readiness.js";
import { loadGatewayTlsRuntime } from "./server/tls.js";
import {
@@ -511,6 +512,7 @@ export async function startGatewayServer(
tailscaleMode,
} = runtimeConfig;
let hooksConfig = runtimeConfig.hooksConfig;
let hookClientIpConfig = resolveHookClientIpConfig(cfgAtStart);
const canvasHostEnabled = runtimeConfig.canvasHostEnabled;
// Create auth rate limiters used by connect/auth flows.
@@ -613,6 +615,7 @@ export async function startGatewayServer(
rateLimiter: authRateLimiter,
gatewayTls,
hooksConfig: () => hooksConfig,
getHookClientIpConfig: () => hookClientIpConfig,
pluginRegistry,
deps,
canvasRuntime,
@@ -954,6 +957,7 @@ export async function startGatewayServer(
broadcast,
getState: () => ({
hooksConfig,
hookClientIpConfig,
heartbeatRunner,
cronState,
browserControl,
@@ -961,6 +965,7 @@ export async function startGatewayServer(
}),
setState: (nextState) => {
hooksConfig = nextState.hooksConfig;
hookClientIpConfig = nextState.hookClientIpConfig;
heartbeatRunner = nextState.heartbeatRunner;
cronState = nextState.cronState;
cron = cronState.cron;

View File

@@ -1,6 +1,6 @@
import { randomUUID } from "node:crypto";
import type { CliDeps } from "../../cli/deps.js";
import { loadConfig } from "../../config/config.js";
import { loadConfig, type OpenClawConfig } from "../../config/config.js";
import { resolveMainSessionKeyFromConfig } from "../../config/sessions.js";
import { runCronIsolatedAgentTurn } from "../../cron/isolated-agent.js";
import type { CronJob } from "../../cron/types.js";
@@ -12,18 +12,26 @@ import {
type HookAgentDispatchPayload,
type HooksConfigResolved,
} from "../hooks.js";
import { createHooksRequestHandler } from "../server-http.js";
import { createHooksRequestHandler, type HookClientIpConfig } from "../server-http.js";
type SubsystemLogger = ReturnType<typeof createSubsystemLogger>;
export function resolveHookClientIpConfig(cfg: OpenClawConfig): HookClientIpConfig {
return {
trustedProxies: cfg.gateway?.trustedProxies,
allowRealIpFallback: cfg.gateway?.allowRealIpFallback === true,
};
}
export function createGatewayHooksRequestHandler(params: {
deps: CliDeps;
getHooksConfig: () => HooksConfigResolved | null;
getClientIpConfig: () => HookClientIpConfig;
bindHost: string;
port: number;
logHooks: SubsystemLogger;
}) {
const { deps, getHooksConfig, bindHost, port, logHooks } = params;
const { deps, getHooksConfig, getClientIpConfig, bindHost, port, logHooks } = params;
const dispatchWakeHook = (value: { text: string; mode: "now" | "next-heartbeat" }) => {
const sessionKey = resolveMainSessionKeyFromConfig();
@@ -108,13 +116,7 @@ export function createGatewayHooksRequestHandler(params: {
bindHost,
port,
logHooks,
getClientIpConfig: () => {
const cfg = loadConfig();
return {
trustedProxies: cfg.gateway?.trustedProxies,
allowRealIpFallback: cfg.gateway?.allowRealIpFallback === true,
};
},
getClientIpConfig,
dispatchAgentHook,
dispatchWakeHook,
});