Skip to content

Commit bf661cc

Browse files
Merge pull request #464 from AikidoSec/undici-v7
Test all supported undici versions: v4, v5, v6 and v7
2 parents d643665 + a40d851 commit bf661cc

16 files changed

+525
-397
lines changed

library/agent/hooks/Package.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ type PackageName = string;
1212
export class Package {
1313
private versions: VersionedPackage[] = [];
1414

15-
constructor(private readonly packageName: PackageName) {
16-
if (!this.packageName) {
15+
constructor(private packageName: PackageName) {
16+
this.assertValidPackageName(this.packageName);
17+
}
18+
19+
private assertValidPackageName(name: string) {
20+
if (!name) {
1721
throw new Error("Package name is required");
1822
}
1923
}
@@ -22,6 +26,11 @@ export class Package {
2226
return this.packageName;
2327
}
2428

29+
setName(name: string) {
30+
this.assertValidPackageName(name);
31+
this.packageName = name;
32+
}
33+
2534
withVersion(range: string): VersionedPackage {
2635
const pkg = new VersionedPackage(range);
2736
this.versions.push(pkg);

library/agent/hooks/wrapRequire.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,29 @@ function executeInterceptors(
305305
export function getOriginalRequire() {
306306
return originalRequire;
307307
}
308+
309+
// In order to support multiple versions of the same package, we need to rewrite the package name
310+
// e.g. In our sources and sinks, we use the real package name `hooks.addPackage("undici")`
311+
// but in the tests we want to `require("undici-v6")` instead of `require("undici")`
312+
export function __internalRewritePackageName(
313+
packageName: string,
314+
aliasForTesting: string
315+
) {
316+
if (!isRequireWrapped) {
317+
throw new Error(
318+
"Start the agent before calling __internalRewritePackageName(..)"
319+
);
320+
}
321+
322+
if (packages.length === 0) {
323+
throw new Error("No packages to patch");
324+
}
325+
326+
const pkg = packages.find((pkg) => pkg.getName() === packageName);
327+
328+
if (!pkg) {
329+
throw new Error(`Could not find package ${packageName}`);
330+
}
331+
332+
pkg.setName(aliasForTesting);
333+
}

library/helpers/startTestAgent.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { ReportingAPI } from "../agent/api/ReportingAPI";
2+
import type { Token } from "../agent/api/Token";
3+
import { __internalRewritePackageName } from "../agent/hooks/wrapRequire";
4+
import type { Logger } from "../agent/logger/Logger";
5+
import { Wrapper } from "../agent/Wrapper";
6+
import { createTestAgent } from "./createTestAgent";
7+
8+
type PackageName = string;
9+
type AliasToRequire = string;
10+
11+
/**
12+
* Start a test agent for testing purposes
13+
*/
14+
export function startTestAgent(opts: {
15+
block?: boolean;
16+
logger?: Logger;
17+
api?: ReportingAPI;
18+
token?: Token;
19+
serverless?: string;
20+
wrappers: Wrapper[];
21+
rewrite: Record<PackageName, AliasToRequire>;
22+
}) {
23+
const agent = createTestAgent(opts);
24+
agent.start(opts.wrappers);
25+
26+
// In order to support multiple versions of the same package, we need to rewrite the package name
27+
// e.g. In our sources and sinks, we use the real package name `hooks.addPackage("undici")`
28+
// but in the tests we want to `require("undici-v6")` instead of `require("undici")`
29+
// The `__internalRewritePackageName` function allows us to do this
30+
Object.keys(opts.rewrite).forEach((packageName) => {
31+
__internalRewritePackageName(packageName, opts.rewrite[packageName]);
32+
});
33+
34+
return agent;
35+
}

library/package-lock.json

Lines changed: 54 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

library/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,12 @@
9696
"tap": "^18.6.1",
9797
"type-fest": "^4.24.0",
9898
"typescript": "^5.3.3",
99-
"undici": "^6.12.0",
10099
"xml-js": "^1.6.11",
101-
"xml2js": "^0.6.2"
100+
"xml2js": "^0.6.2",
101+
"undici-v4": "npm:undici@^4.0.0",
102+
"undici-v5": "npm:undici@^5.0.0",
103+
"undici-v6": "npm:undici@^6.0.0",
104+
"undici-v7": "npm:undici@^7.0.0"
102105
},
103106
"scripts": {
104107
"test": "node ../scripts/run-tap.js",

library/sinks/Undici.custom.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import * as dns from "dns";
33
import * as t from "tap";
44
import { Token } from "../agent/api/Token";
55
import { Context, runWithContext } from "../agent/Context";
6+
import { startTestAgent } from "../helpers/startTestAgent";
67
import { wrap } from "../helpers/wrap";
78
import { getMajorNodeVersion } from "../helpers/getNodeVersion";
89
import { Undici } from "./Undici";
9-
import { createTestAgent } from "../helpers/createTestAgent";
1010

1111
function createContext(): Context {
1212
return {
@@ -42,13 +42,14 @@ t.test(
4242
getMajorNodeVersion() <= 16 ? "ReadableStream is not available" : false,
4343
},
4444
async (t) => {
45-
const agent = createTestAgent({
45+
startTestAgent({
4646
token: new Token("123"),
47+
wrappers: [new Undici()],
48+
rewrite: { undici: "undici-v6" },
4749
});
48-
agent.start([new Undici()]);
4950

5051
const { request, Dispatcher, setGlobalDispatcher, getGlobalDispatcher } =
51-
require("undici") as typeof import("undici");
52+
require("undici-v6") as typeof import("undici-v6");
5253

5354
// See https://www.npmjs.com/package/@n8n_io/license-sdk
5455
// They set a custom dispatcher to proxy certain requests

library/sinks/Undici.localhost.test.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
/* eslint-disable prefer-rest-params */
22
import * as t from "tap";
3-
import { Agent } from "../agent/Agent";
43
import { createServer, Server } from "http";
5-
import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting";
64
import { Token } from "../agent/api/Token";
75
import { Context, runWithContext } from "../agent/Context";
8-
import { LoggerNoop } from "../agent/logger/LoggerNoop";
9-
import { createTestAgent } from "../helpers/createTestAgent";
106
import { getMajorNodeVersion } from "../helpers/getNodeVersion";
7+
import { startTestAgent } from "../helpers/startTestAgent";
118
import { Undici } from "./Undici";
129

1310
function createContext({
@@ -53,12 +50,12 @@ function createContext({
5350
};
5451
}
5552

56-
const agent = createTestAgent({
53+
startTestAgent({
5754
token: new Token("123"),
55+
wrappers: [new Undici()],
56+
rewrite: { undici: "undici-v6" },
5857
});
5958

60-
agent.start([new Undici()]);
61-
6259
const port = 1346;
6360
const serverUrl = `http://localhost:${port}`;
6461
const hostHeader = `localhost:${port}`;
@@ -83,7 +80,7 @@ t.test(
8380
getMajorNodeVersion() <= 16 ? "ReadableStream is not available" : false,
8481
},
8582
async (t) => {
86-
const { request } = require("undici");
83+
const { request } = require("undici-v6") as typeof import("undici-v6");
8784

8885
await runWithContext(
8986
createContext({
@@ -108,7 +105,7 @@ t.test(
108105
getMajorNodeVersion() <= 16 ? "ReadableStream is not available" : false,
109106
},
110107
async (t) => {
111-
const { request } = require("undici");
108+
const { request } = require("undici-v6") as typeof import("undici-v6");
112109

113110
const error = await t.rejects(async () => {
114111
await runWithContext(

0 commit comments

Comments
 (0)