From 9b97add1aebb47b2521f5349e34f1389fa8d305a Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 5 Apr 2026 21:42:32 +0200 Subject: [PATCH] fix cors function for alpine linux (#4091) I provide docker images with alpine linux and tested the new cors approach. It didn't work because after calling ```js const dispatcher = new Agent({ connect: { lookup: (_h, _o, cb) => cb(null, address, family) } }); ``` the dispatcher variable was undefined. This PR solves this and I tested this under debian too. The mix of internal fetch and newer undici did not work and alpine needs additionally the `process.nextTick`. --------- Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> --- js/server_functions.js | 13 ++++++++++--- tests/unit/functions/server_functions_spec.js | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/js/server_functions.js b/js/server_functions.js index 9d4aff47..9650257c 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -2,7 +2,7 @@ const dns = require("node:dns"); const fs = require("node:fs"); const path = require("node:path"); const ipaddr = require("ipaddr.js"); -const { Agent } = require("undici"); +const undici = require("undici"); const Log = require("logger"); const startUp = new Date(); @@ -98,9 +98,16 @@ async function cors (req, res) { } // Pin the validated IP — fetch() reuses it instead of doing its own DNS lookup - const dispatcher = new Agent({ connect: { lookup: (_h, _o, cb) => cb(null, address, family) } }); + const dispatcher = new undici.Agent({ + connect: { + lookup: (_h, _o, cb) => { + const addresses = [{ address: address, family: family }]; + process.nextTick(() => cb(null, addresses)); + } + } + }); - const response = await fetch(url, { dispatcher, headers: headersToSend }); + const response = await undici.fetch(url, { dispatcher, headers: headersToSend }); if (response.ok) { for (const header of expectedReceivedHeaders) { const headerValue = response.headers.get(header); diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index ebb1d678..779daaf0 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -1,9 +1,10 @@ -// Tests use vi.spyOn on shared module objects (dns, global.fetch). +// Tests use vi.spyOn on shared module objects (dns, undici). // vi.spyOn modifies the object property directly on the cached module instance, so it // is intercepted by server_functions.js regardless of the Module.prototype.require override // in vitest-setup.js. restoreAllMocks:true auto-restores spies, but may reuse the same // spy instance — mockClear() is called explicitly in beforeEach to reset call history. const dns = require("node:dns"); +const undici = require("undici"); const { cors, getUserAgent, replaceSecretPlaceholder } = require("#server_functions"); describe("server_functions tests", () => { @@ -41,7 +42,7 @@ describe("server_functions tests", () => { // vi.spyOn may return the same spy instance across tests when restoreAllMocks // restores-but-reuses; mockClear() explicitly resets call history each time. - fetchSpy = vi.spyOn(global, "fetch"); + fetchSpy = vi.spyOn(undici, "fetch"); fetchSpy.mockClear(); fetchSpy.mockImplementation(() => Promise.resolve({ headers: { get: fetchResponseHeadersGet },