fix(slack): preserve debug capture with proxies

This commit is contained in:
Dallin Romney
2026-08-01 23:04:36 +08:00
parent cf405b1e07
commit de86be4cde
2 changed files with 30 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ import {
resolveFetch,
resolveEnvHttpProxyAgentOptions,
} from "openclaw/plugin-sdk/fetch-runtime";
import { isDebugProxyGlobalFetchPatchInstalled } from "openclaw/plugin-sdk/proxy-capture";
import type { EnvHttpProxyAgent } from "undici";
type SlackUndiciRuntime = Pick<typeof import("undici"), "EnvHttpProxyAgent" | "fetch">;
@@ -57,7 +58,9 @@ export function resolveSlackProxyDispatcher(): SlackProxyDispatcher | undefined
function buildSlackFetch(
dispatcher?: SlackProxyDispatcher,
): NonNullable<WebClientOptions["fetch"]> | undefined {
if (!dispatcher) {
if (!dispatcher || isDebugProxyGlobalFetchPatchInstalled()) {
// Debug capture patches global fetch after installing its proxy-aware dispatcher.
// A package-owned fetch would bypass capture whenever ambient proxy env is present.
return resolveFetch() as NonNullable<WebClientOptions["fetch"]> | undefined;
}
const { fetch: slackFetch } = loadSlackUndiciRuntime();

View File

@@ -5,6 +5,14 @@ import path from "node:path";
import type { WebClientOptions } from "@slack/web-api";
import { afterEach, beforeAll, beforeEach, describe, expect, expectTypeOf, it, vi } from "vitest";
const { isDebugProxyGlobalFetchPatchInstalledMock } = vi.hoisted(() => ({
isDebugProxyGlobalFetchPatchInstalledMock: vi.fn(() => false),
}));
vi.mock("openclaw/plugin-sdk/proxy-capture", () => ({
isDebugProxyGlobalFetchPatchInstalled: isDebugProxyGlobalFetchPatchInstalledMock,
}));
vi.mock("@slack/web-api", () => {
const WebClient = vi.fn(function WebClientMock(
this: Record<string, unknown>,
@@ -119,6 +127,7 @@ beforeEach(() => {
WebClient.mockClear();
clearSlackWriteClientCacheForTest();
clearSlackApiUrlEnvForTest();
isDebugProxyGlobalFetchPatchInstalledMock.mockReturnValue(false);
});
afterEach(() => {
@@ -406,6 +415,23 @@ describe("slack proxy dispatcher", () => {
await dispatcher?.close();
});
it("keeps the capture-patched global fetch with ambient proxy env", async () => {
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
isDebugProxyGlobalFetchPatchInstalledMock.mockReturnValue(true);
const globalFetch = vi
.spyOn(globalThis, "fetch")
.mockResolvedValue(new Response(null, { status: 200 }));
const dispatcher = resolveSlackProxyDispatcher();
try {
const options = resolveSlackWebClientOptions({}, dispatcher);
await requireFetch(options)("https://slack.com/api/auth.test");
expect(globalFetch).toHaveBeenCalledOnce();
} finally {
globalFetch.mockRestore();
await dispatcher?.close();
}
});
it("creates the dispatcher while managed proxy CA trust is active", async () => {
const caFile = writeTempCa("slack-managed-proxy-ca");
process.env.HTTPS_PROXY = "https://proxy.example.com:8443";