diff --git a/js/http_fetcher.js b/js/http_fetcher.js index 830b08bd17..0766168401 100644 --- a/js/http_fetcher.js +++ b/js/http_fetcher.js @@ -1,5 +1,5 @@ const { EventEmitter } = require("node:events"); -const { Agent } = require("undici"); +const { fetch: undiciFetch, Agent } = require("undici"); const Log = require("logger"); const { getUserAgent } = require("#server_functions"); @@ -263,8 +263,13 @@ class HTTPFetcher extends EventEmitter { const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { - const response = await fetch(this.url, { - ...this.getRequestOptions(), + const requestOptions = this.getRequestOptions(); + // Use undici.fetch when a custom dispatcher is present (e.g. selfSignedCert), + // because Node's global fetch and npm undici@8 Agents are incompatible. + // For regular requests, use globalThis.fetch so MSW and other interceptors work. + const fetchFn = requestOptions.dispatcher ? undiciFetch : globalThis.fetch; + const response = await fetchFn(this.url, { + ...requestOptions, signal: controller.signal }); diff --git a/tests/unit/functions/http_fetcher_spec.js b/tests/unit/functions/http_fetcher_spec.js index 046ddb9ca0..0d8d41be50 100644 --- a/tests/unit/functions/http_fetcher_spec.js +++ b/tests/unit/functions/http_fetcher_spec.js @@ -440,3 +440,32 @@ describe("fetch() method", () => { expect(errorInfo.errorType).toBe("NETWORK_ERROR"); }); }); + +describe("selfSignedCert dispatcher", () => { + const { Agent } = require("undici"); + + it("should set rejectUnauthorized=false when selfSignedCert is true", () => { + fetcher = new HTTPFetcher(TEST_URL, { + reloadInterval: 60000, + selfSignedCert: true + }); + + const options = fetcher.getRequestOptions(); + + expect(options.dispatcher).toBeInstanceOf(Agent); + const agentOptionsSymbol = Object.getOwnPropertySymbols(options.dispatcher).find((s) => s.description === "options"); + const dispatcherOptions = options.dispatcher[agentOptionsSymbol]; + expect(dispatcherOptions.connect.rejectUnauthorized).toBe(false); + }); + + it("should not set a dispatcher when selfSignedCert is false", () => { + fetcher = new HTTPFetcher(TEST_URL, { + reloadInterval: 60000, + selfSignedCert: false + }); + + const options = fetcher.getRequestOptions(); + + expect(options.dispatcher).toBeUndefined(); + }); +});