diff --git a/src/outbound.ts b/src/outbound.ts index ca12404..803d38a 100644 --- a/src/outbound.ts +++ b/src/outbound.ts @@ -1,7 +1,7 @@ import { lookup } from "node:dns/promises"; import { BlockList, isIP } from "node:net"; import type { LookupFunction } from "node:net"; -import { Agent } from "undici"; +import { Agent, fetch as undiciFetch } from "undici"; import type { SiteConfig } from "./types.js"; import { isSameSite } from "./url.js"; @@ -55,7 +55,7 @@ export class OutboundClient { dependencies: OutboundDependencies = {} ) { this.remainingRequests = site.crawl.maxUrls + EXTRA_SCAN_REQUESTS; - this.fetchImpl = dependencies.fetch ?? fetch; + this.fetchImpl = dependencies.fetch ?? (undiciFetch as unknown as typeof fetch); this.resolve = dependencies.resolve ?? resolveAddresses; } diff --git a/test/security.test.ts b/test/security.test.ts index 60672e5..93da76e 100644 --- a/test/security.test.ts +++ b/test/security.test.ts @@ -1,3 +1,5 @@ +import { once } from "node:events"; +import { createServer } from "node:http"; import { describe, expect, it, vi } from "vitest"; import { isPublicAddress, OutboundClient, pinnedLookup } from "../src/outbound.js"; import type { SiteConfig } from "../src/types.js"; @@ -99,4 +101,30 @@ describe("hardening input remoti", () => { expect(dispatchers.size).toBe(1); expect(resolve).toHaveBeenCalledOnce(); }); + + it("usa un fetch compatibile con il dispatcher installato", async () => { + const server = createServer((_request, response) => response.end("ok")); + server.listen(0, "127.0.0.1"); + await once(server, "listening"); + const address = server.address(); + if (!address || typeof address === "string") throw new Error("Fixture HTTP non disponibile."); + + const localSite = { + ...site, + roots: [`http://example.test:${address.port}/`] + }; + const client = new OutboundClient(localSite); + Object.defineProperty(client, "resolvePinnedAddresses", { + value: async () => [{ address: "127.0.0.1", family: 4 }] + }); + + try { + const response = await client.get(localSite.roots[0], { maxBytes: 10 }); + expect(new TextDecoder().decode(response.body)).toBe("ok"); + } finally { + await client.close(); + server.close(); + await once(server, "close"); + } + }); });