diff --git a/package.json b/package.json index 500a89f6..432aea9b 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@types/qs": "^6.9.7", "@types/selfsigned": "^2.0.1", "@types/tar-stream": "^2.2.2", - "@vitest/coverage-v8": "^1.3.1", + "@vitest/coverage-v8": "^3.0.0", "busboy": "^1.6.0", "cross-env": "^7.0.3", "eslint": "^8.25.0", @@ -83,7 +83,7 @@ "tshy": "^1.0.0", "tshy-after": "^1.0.0", "typescript": "^5.0.4", - "vitest": "^1.3.1" + "vitest": "^3.0.0" }, "engines": { "node": ">= 14.19.3" diff --git a/src/HttpClient.ts b/src/HttpClient.ts index 03aed743..79ce22e2 100644 --- a/src/HttpClient.ts +++ b/src/HttpClient.ts @@ -22,8 +22,9 @@ import { request as undiciRequest, Dispatcher, Agent, - getGlobalDispatcher, Pool, + getGlobalDispatcher, + MockAgent, } from 'undici'; import undiciSymbols from 'undici/lib/core/symbols.js'; import { FormData as FormDataNode } from 'formdata-node'; @@ -207,10 +208,23 @@ export class HttpClient extends EventEmitter { } getDispatcher() { - return this.#dispatcher ?? getGlobalDispatcher(); + if (this.#dispatcher) { + return this.#dispatcher; + } + // In a multi-version undici environment + // the global dispatcher is the highest version of undici + // which will conflict with the maxRedirects field and report an error + // so we need to create it that use 5.x version + const globalDispatcher = getGlobalDispatcher(); + if (!(globalDispatcher instanceof Agent) && !(globalDispatcher instanceof MockAgent)) { + const dispatcher = globalDispatcher.constructor.name === 'MockAgent' ? new MockAgent() : new Agent(); + this.setDispatcher(dispatcher); + return dispatcher; + } + return globalDispatcher; } - setDispatcher(dispatcher: Dispatcher) { + setDispatcher(dispatcher?: Dispatcher) { this.#dispatcher = dispatcher; } @@ -415,7 +429,7 @@ export class HttpClient extends EventEmitter { headers, bodyTimeout, opaque: internalOpaque, - dispatcher: args.dispatcher ?? this.#dispatcher, + dispatcher: args.dispatcher ?? this.getDispatcher(), signal: args.signal, }; if (typeof args.highWaterMark === 'number') { diff --git a/test/diagnostics_channel.test.ts b/test/diagnostics_channel.test.ts index a31f9f8b..035b3a39 100644 --- a/test/diagnostics_channel.test.ts +++ b/test/diagnostics_channel.test.ts @@ -1,8 +1,9 @@ import { strict as assert } from 'node:assert'; import diagnosticsChannel from 'node:diagnostics_channel'; import { describe, it, beforeEach, afterEach } from 'vitest'; -import urllib from '../src'; -import type { +import urllib, { getGlobalDispatcher, setGlobalDispatcher } from '../src'; +import { + MockAgent, RequestDiagnosticsMessage, ResponseDiagnosticsMessage, } from '../src'; @@ -13,14 +14,22 @@ import { sleep } from './utils'; describe('diagnostics_channel.test.ts', () => { let close: any; let _url: string; + + let mockAgent: MockAgent; + const globalAgent = getGlobalDispatcher(); + beforeEach(async () => { const { closeServer, url } = await startServer(); close = closeServer; _url = url; + mockAgent = new MockAgent(); + setGlobalDispatcher(mockAgent); }); afterEach(async () => { await close(); + setGlobalDispatcher(globalAgent); + await mockAgent.close(); }); it('should support trace socket info by undici:client:sendHeaders and undici:request:trailers', async () => { diff --git a/test/index.test.ts b/test/index.test.ts index 90a677c0..4928cd37 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -180,11 +180,15 @@ describe('index.test.ts', () => { const globalAgent = getGlobalDispatcher(); beforeEach(() => { mockAgent = new MockAgent(); + const httpClient = getDefaultHttpClient(); + httpClient.setDispatcher(mockAgent); setGlobalDispatcher(mockAgent); }); afterEach(async () => { setGlobalDispatcher(globalAgent); + const httpClient = getDefaultHttpClient(); + httpClient.setDispatcher(); await mockAgent.close(); }); diff --git a/test/options.retry.test.ts b/test/options.retry.test.ts index 8313e64c..763b559b 100644 --- a/test/options.retry.test.ts +++ b/test/options.retry.test.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'node:assert'; import { createWriteStream, createReadStream } from 'node:fs'; import { describe, it, beforeAll, afterAll, beforeEach, afterEach } from 'vitest'; -import urllib from '../src'; +import urllib, { getGlobalDispatcher, MockAgent, setGlobalDispatcher } from '../src'; import { startServer } from './fixtures/server'; import { readableToString, createTempfile } from './utils'; @@ -11,6 +11,9 @@ describe('options.retry.test.ts', () => { let tmpfile: string; let cleanup: any; + let mockAgent: MockAgent; + const globalAgent = getGlobalDispatcher(); + beforeAll(async () => { const { closeServer, url } = await startServer(); close = closeServer; @@ -24,9 +27,13 @@ describe('options.retry.test.ts', () => { const item = await createTempfile(); tmpfile = item.tmpfile; cleanup = item.cleanup; + mockAgent = new MockAgent(); + setGlobalDispatcher(mockAgent); }); afterEach(async () => { await cleanup(); + setGlobalDispatcher(globalAgent); + await mockAgent.close(); }); it('should not retry on 400', async () => { diff --git a/test/options.timing.test.ts b/test/options.timing.test.ts index c6d2ca41..6e3909ce 100644 --- a/test/options.timing.test.ts +++ b/test/options.timing.test.ts @@ -1,6 +1,6 @@ import { strict as assert } from 'node:assert'; import { describe, it, beforeAll, afterAll } from 'vitest'; -import urllib from '../src'; +import urllib, { getGlobalDispatcher, MockAgent, setGlobalDispatcher } from '../src'; import { RawResponseWithMeta } from '../src/Response'; import { startServer } from './fixtures/server'; import { sleep } from './utils'; @@ -8,14 +8,21 @@ import { sleep } from './utils'; describe('options.timing.test.ts', () => { let close: any; let _url: string; + + let mockAgent: MockAgent; + const globalAgent = getGlobalDispatcher(); beforeAll(async () => { const { closeServer, url } = await startServer(); close = closeServer; _url = url; + mockAgent = new MockAgent(); + setGlobalDispatcher(mockAgent); }); afterAll(async () => { await close(); + setGlobalDispatcher(globalAgent); + await mockAgent.close(); }); it('should timing = true work', async () => {