From 46d93088726712ff0ff128363a77bc307e1c9798 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Sun, 15 May 2022 15:27:38 +0200 Subject: [PATCH] deps: update undici to 5.2.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/43059 Reviewed-By: Robert Nagy Reviewed-By: Filip Skokan Reviewed-By: Matteo Collina Reviewed-By: Mohammed Keyvanzadeh Reviewed-By: Tobias Nießen Reviewed-By: Luigi Pinca Reviewed-By: Darshan Sen Reviewed-By: Rich Trott --- deps/undici/src/README.md | 15 ++ deps/undici/src/docs/api/Errors.md | 1 - deps/undici/src/index-fetch.js | 9 +- deps/undici/src/index.js | 16 +-- deps/undici/src/lib/client.js | 24 +--- deps/undici/src/lib/core/errors.js | 11 -- deps/undici/src/lib/fetch/headers.js | 129 ++++++++++------- deps/undici/src/lib/fetch/index.js | 5 + deps/undici/src/lib/fetch/request.js | 15 +- deps/undici/src/lib/global.js | 32 +++++ deps/undici/src/lib/mock/mock-utils.js | 3 +- deps/undici/src/package.json | 9 +- deps/undici/src/types/fetch.d.ts | 25 +++- deps/undici/undici.js | 186 ++++++++++++------------- 14 files changed, 256 insertions(+), 224 deletions(-) create mode 100644 deps/undici/src/lib/global.js diff --git a/deps/undici/src/README.md b/deps/undici/src/README.md index e0af350ec7d555..5acff95e270088 100644 --- a/deps/undici/src/README.md +++ b/deps/undici/src/README.md @@ -194,6 +194,21 @@ Basic usage example: } ``` +You can pass an optional dispatcher to `fetch` as: + +```js +import { fetch, Agent } from 'undici' + +const res = await fetch('https://example.com', { + // Mocks are also supported + dispatcher: new Agent({ + keepAliveTimeout: 10, + keepAliveMaxTimeout: 10 + }) +}) +const json = await res.json() +console.log(json) +``` #### `request.body` diff --git a/deps/undici/src/docs/api/Errors.md b/deps/undici/src/docs/api/Errors.md index 406fd5c40fc9c9..6287ddcfd0becc 100644 --- a/deps/undici/src/docs/api/Errors.md +++ b/deps/undici/src/docs/api/Errors.md @@ -19,7 +19,6 @@ import { errors } from 'undici' | `RequestContentLengthMismatchError` | `UND_ERR_REQ_CONTENT_LENGTH_MISMATCH` | request body does not match content-length header | | `ResponseContentLengthMismatchError` | `UND_ERR_RES_CONTENT_LENGTH_MISMATCH` | response body does not match content-length header | | `InformationalError` | `UND_ERR_INFO` | expected error with reason | -| `TrailerMismatchError` | `UND_ERR_TRAILER_MISMATCH` | trailers did not match specification | ### `SocketError` diff --git a/deps/undici/src/index-fetch.js b/deps/undici/src/index-fetch.js index aaf70af701d816..2ee12fc1ef77e6 100644 --- a/deps/undici/src/index-fetch.js +++ b/deps/undici/src/index-fetch.js @@ -1,12 +1,11 @@ 'use strict' -const Agent = require('./lib/agent') - -const globalDispatcher = new Agent() - +const { getGlobalDispatcher } = require('./lib/global') const fetchImpl = require('./lib/fetch') + module.exports.fetch = async function fetch (resource) { - return fetchImpl.apply(globalDispatcher, arguments) + const dispatcher = (arguments[1] && arguments[1].dispatcher) || getGlobalDispatcher() + return fetchImpl.apply(dispatcher, arguments) } module.exports.FormData = require('./lib/fetch/formdata').FormData module.exports.Headers = require('./lib/fetch/headers').Headers diff --git a/deps/undici/src/index.js b/deps/undici/src/index.js index 888eb6a5a4f3d3..2248619749ceaf 100644 --- a/deps/undici/src/index.js +++ b/deps/undici/src/index.js @@ -15,6 +15,7 @@ const MockAgent = require('./lib/mock/mock-agent') const MockPool = require('./lib/mock/mock-pool') const mockErrors = require('./lib/mock/mock-errors') const ProxyAgent = require('./lib/proxy-agent') +const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global') const nodeVersion = process.versions.node.split('.') const nodeMajor = Number(nodeVersion[0]) @@ -32,19 +33,6 @@ module.exports.ProxyAgent = ProxyAgent module.exports.buildConnector = buildConnector module.exports.errors = errors -let globalDispatcher = new Agent() - -function setGlobalDispatcher (agent) { - if (!agent || typeof agent.dispatch !== 'function') { - throw new InvalidArgumentError('Argument agent must implement Agent') - } - globalDispatcher = agent -} - -function getGlobalDispatcher () { - return globalDispatcher -} - function makeDispatcher (fn) { return (url, opts, handler) => { if (typeof opts === 'function') { @@ -98,7 +86,7 @@ if (nodeMajor > 16 || (nodeMajor === 16 && nodeMinor >= 5)) { if (!fetchImpl) { fetchImpl = require('./lib/fetch') } - const dispatcher = getGlobalDispatcher() + const dispatcher = (arguments[1] && arguments[1].dispatcher) || getGlobalDispatcher() return fetchImpl.apply(dispatcher, arguments) } module.exports.Headers = require('./lib/fetch/headers').Headers diff --git a/deps/undici/src/lib/client.js b/deps/undici/src/lib/client.js index d3d4cfc705d635..1e23e7aad34d60 100644 --- a/deps/undici/src/lib/client.js +++ b/deps/undici/src/lib/client.js @@ -11,7 +11,6 @@ const RedirectHandler = require('./handler/redirect') const { RequestContentLengthMismatchError, ResponseContentLengthMismatchError, - TrailerMismatchError, InvalidArgumentError, RequestAbortedError, HeadersTimeoutError, @@ -425,7 +424,6 @@ class Parser { this.bytesRead = 0 - this.trailer = '' this.keepAlive = '' this.contentLength = '' } @@ -615,8 +613,6 @@ class Parser { const key = this.headers[len - 2] if (key.length === 10 && key.toString().toLowerCase() === 'keep-alive') { this.keepAlive += buf.toString() - } else if (key.length === 7 && key.toString().toLowerCase() === 'trailer') { - this.trailer += buf.toString() } else if (key.length === 14 && key.toString().toLowerCase() === 'content-length') { this.contentLength += buf.toString() } @@ -819,7 +815,7 @@ class Parser { } onMessageComplete () { - const { client, socket, statusCode, upgrade, trailer, headers, contentLength, bytesRead, shouldKeepAlive } = this + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this if (socket.destroyed && (!statusCode || shouldKeepAlive)) { return -1 @@ -838,7 +834,6 @@ class Parser { this.statusText = '' this.bytesRead = 0 this.contentLength = '' - this.trailer = '' this.keepAlive = '' assert(this.headers.length % 2 === 0) @@ -849,23 +844,6 @@ class Parser { return } - const trailers = trailer ? trailer.split(/,\s*/) : [] - for (let i = 0; i < trailers.length; i++) { - const trailer = trailers[i] - let found = false - for (let n = 0; n < headers.length; n += 2) { - const key = headers[n] - if (key.length === trailer.length && key.toString().toLowerCase() === trailer.toLowerCase()) { - found = true - break - } - } - if (!found) { - util.destroy(socket, new TrailerMismatchError()) - return -1 - } - } - /* istanbul ignore next: should be handled by llhttp? */ if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { util.destroy(socket, new ResponseContentLengthMismatchError()) diff --git a/deps/undici/src/lib/core/errors.js b/deps/undici/src/lib/core/errors.js index a36107c5a9811e..f480f31a176acf 100644 --- a/deps/undici/src/lib/core/errors.js +++ b/deps/undici/src/lib/core/errors.js @@ -116,16 +116,6 @@ class ResponseContentLengthMismatchError extends UndiciError { } } -class TrailerMismatchError extends UndiciError { - constructor (message) { - super(message) - Error.captureStackTrace(this, TrailerMismatchError) - this.name = 'TrailerMismatchError' - this.message = message || 'Trailers does not match trailer header' - this.code = 'UND_ERR_TRAILER_MISMATCH' - } -} - class ClientDestroyedError extends UndiciError { constructor (message) { super(message) @@ -196,7 +186,6 @@ module.exports = { BodyTimeoutError, RequestContentLengthMismatchError, ConnectTimeoutError, - TrailerMismatchError, InvalidArgumentError, InvalidReturnValueError, RequestAbortedError, diff --git a/deps/undici/src/lib/fetch/headers.js b/deps/undici/src/lib/fetch/headers.js index e0295be2250ce1..eb4eb47c4ec058 100644 --- a/deps/undici/src/lib/fetch/headers.js +++ b/deps/undici/src/lib/fetch/headers.js @@ -77,6 +77,33 @@ function fill (headers, object) { } } +// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object +const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) + +// https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object +function makeHeadersIterator (iterator) { + const i = { + next () { + if (Object.getPrototypeOf(this) !== i) { + throw new TypeError( + '\'next\' called on an object that does not implement interface Headers Iterator.' + ) + } + + return iterator.next() + }, + // The class string of an iterator prototype object for a given interface is the + // result of concatenating the identifier of the interface and the string " Iterator". + [Symbol.toStringTag]: 'Headers Iterator' + } + + // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%. + Object.setPrototypeOf(i, esIteratorPrototype) + // esIteratorPrototype needs to be the prototype of i + // which is the prototype of an empty object. Yes, it's confusing. + return Object.setPrototypeOf({}, i) +} + class HeadersList { constructor (init) { if (init instanceof HeadersList) { @@ -169,32 +196,22 @@ class Headers { } get [Symbol.toStringTag] () { - if (!(this instanceof Headers)) { - throw new TypeError('Illegal invocation') - } - return this.constructor.name } - toString () { + // https://fetch.spec.whatwg.org/#dom-headers-append + append (name, value) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - return Object.prototype.toString.call(this) - } - - append (...args) { - if (!(this instanceof Headers)) { - throw new TypeError('Illegal invocation') - } - if (args.length < 2) { + if (arguments.length < 2) { throw new TypeError( - `Failed to execute 'append' on 'Headers': 2 arguments required, but only ${args.length} present.` + `Failed to execute 'append' on 'Headers': 2 arguments required, but only ${arguments.length} present.` ) } - const normalizedName = normalizeAndValidateHeaderName(String(args[0])) + const normalizedName = normalizeAndValidateHeaderName(String(name)) if (this[kGuard] === 'immutable') { throw new TypeError('immutable') @@ -212,20 +229,22 @@ class Headers { return } - return this[kHeadersList].append(String(args[0]), String(args[1])) + return this[kHeadersList].append(String(name), String(value)) } - delete (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete (name) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 1) { + + if (arguments.length < 1) { throw new TypeError( - `Failed to execute 'delete' on 'Headers': 1 argument required, but only ${args.length} present.` + `Failed to execute 'delete' on 'Headers': 1 argument required, but only ${arguments.length} present.` ) } - const normalizedName = normalizeAndValidateHeaderName(String(args[0])) + const normalizedName = normalizeAndValidateHeaderName(String(name)) if (this[kGuard] === 'immutable') { throw new TypeError('immutable') @@ -243,42 +262,48 @@ class Headers { return } - return this[kHeadersList].delete(String(args[0])) + return this[kHeadersList].delete(String(name)) } - get (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-get + get (name) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 1) { + + if (arguments.length < 1) { throw new TypeError( - `Failed to execute 'get' on 'Headers': 1 argument required, but only ${args.length} present.` + `Failed to execute 'get' on 'Headers': 1 argument required, but only ${arguments.length} present.` ) } - return this[kHeadersList].get(String(args[0])) + return this[kHeadersList].get(String(name)) } - has (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-has + has (name) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 1) { + + if (arguments.length < 1) { throw new TypeError( - `Failed to execute 'has' on 'Headers': 1 argument required, but only ${args.length} present.` + `Failed to execute 'has' on 'Headers': 1 argument required, but only ${arguments.length} present.` ) } - return this[kHeadersList].has(String(args[0])) + return this[kHeadersList].has(String(name)) } - set (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-set + set (name, value) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 2) { + + if (arguments.length < 2) { throw new TypeError( - `Failed to execute 'set' on 'Headers': 2 arguments required, but only ${args.length} present.` + `Failed to execute 'set' on 'Headers': 2 arguments required, but only ${arguments.length} present.` ) } @@ -286,19 +311,19 @@ class Headers { throw new TypeError('immutable') } else if ( this[kGuard] === 'request' && - forbiddenHeaderNames.includes(String(args[0]).toLocaleLowerCase()) + forbiddenHeaderNames.includes(String(name).toLocaleLowerCase()) ) { return } else if (this[kGuard] === 'request-no-cors') { // TODO } else if ( this[kGuard] === 'response' && - forbiddenResponseHeaderNames.includes(String(args[0]).toLocaleLowerCase()) + forbiddenResponseHeaderNames.includes(String(name).toLocaleLowerCase()) ) { return } - return this[kHeadersList].set(String(args[0]), String(args[1])) + return this[kHeadersList].set(String(name), String(value)) } get [kHeadersSortedMap] () { @@ -311,7 +336,7 @@ class Headers { throw new TypeError('Illegal invocation') } - return this[kHeadersSortedMap].keys() + return makeHeadersIterator(this[kHeadersSortedMap].keys()) } values () { @@ -319,7 +344,7 @@ class Headers { throw new TypeError('Illegal invocation') } - return this[kHeadersSortedMap].values() + return makeHeadersIterator(this[kHeadersSortedMap].values()) } entries () { @@ -327,37 +352,33 @@ class Headers { throw new TypeError('Illegal invocation') } - return this[kHeadersSortedMap].entries() + return makeHeadersIterator(this[kHeadersSortedMap].entries()) } - [Symbol.iterator] () { + /** + * @param {(value: string, key: string, self: Headers) => void} callbackFn + * @param {unknown} thisArg + */ + forEach (callbackFn, thisArg = globalThis) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - return this[kHeadersSortedMap] - } - - forEach (...args) { - if (!(this instanceof Headers)) { - throw new TypeError('Illegal invocation') - } - if (args.length < 1) { + if (arguments.length < 1) { throw new TypeError( - `Failed to execute 'forEach' on 'Headers': 1 argument required, but only ${args.length} present.` + `Failed to execute 'forEach' on 'Headers': 1 argument required, but only ${arguments.length} present.` ) } - if (typeof args[0] !== 'function') { + + if (typeof callbackFn !== 'function') { throw new TypeError( "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." ) } - const callback = args[0] - const thisArg = args[1] - this[kHeadersSortedMap].forEach((value, index) => { - callback.apply(thisArg, [value, index, this]) - }) + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]) + } } [Symbol.for('nodejs.util.inspect.custom')] () { diff --git a/deps/undici/src/lib/fetch/index.js b/deps/undici/src/lib/fetch/index.js index ec1503c159e490..5dab8a0532fcf5 100644 --- a/deps/undici/src/lib/fetch/index.js +++ b/deps/undici/src/lib/fetch/index.js @@ -1827,6 +1827,11 @@ async function httpNetworkFetch ( let bytes try { const { done, value } = await fetchParams.controller.next() + + if (isAborted(fetchParams)) { + break + } + bytes = done ? undefined : value } catch (err) { if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { diff --git a/deps/undici/src/lib/fetch/request.js b/deps/undici/src/lib/fetch/request.js index 24210e59044ff2..c17927ee768a39 100644 --- a/deps/undici/src/lib/fetch/request.js +++ b/deps/undici/src/lib/fetch/request.js @@ -419,16 +419,10 @@ class Request { // 4. If headers is a Headers object, then for each header in its header // list, append header’s name/header’s value to this’s headers. - if (headers instanceof Headers) { - // TODO (fix): Why doesn't this work? - // for (const [key, val] of headers[kHeadersList]) { - // this[kHeaders].append(key, val) - // } - - this[kState].headersList = new HeadersList([ - ...this[kState].headersList, - ...headers[kHeadersList] - ]) + if (headers.constructor.name === 'Headers') { + for (const [key, val] of headers[kHeadersList] || headers) { + this[kHeaders].append(key, val) + } } else { // 5. Otherwise, fill this’s headers with headers. fillHeaders(this[kState].headersList, headers) @@ -468,7 +462,6 @@ class Request { // this’s headers. if (contentType && !this[kHeaders].has('content-type')) { this[kHeaders].append('content-type', contentType) - this[kState].headersList.append('content-type', contentType) } } diff --git a/deps/undici/src/lib/global.js b/deps/undici/src/lib/global.js new file mode 100644 index 00000000000000..18bfd73cc9283e --- /dev/null +++ b/deps/undici/src/lib/global.js @@ -0,0 +1,32 @@ +'use strict' + +// We include a version number for the Dispatcher API. In case of breaking changes, +// this version number must be increased to avoid conflicts. +const globalDispatcher = Symbol.for('undici.globalDispatcher.1') +const { InvalidArgumentError } = require('./core/errors') +const Agent = require('./agent') + +if (getGlobalDispatcher() === undefined) { + setGlobalDispatcher(new Agent()) +} + +function setGlobalDispatcher (agent) { + if (!agent || typeof agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument agent must implement Agent') + } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }) +} + +function getGlobalDispatcher () { + return globalThis[globalDispatcher] +} + +module.exports = { + setGlobalDispatcher, + getGlobalDispatcher +} diff --git a/deps/undici/src/lib/mock/mock-utils.js b/deps/undici/src/lib/mock/mock-utils.js index 1912a38fc485f5..a81f05af045de7 100644 --- a/deps/undici/src/lib/mock/mock-utils.js +++ b/deps/undici/src/lib/mock/mock-utils.js @@ -229,8 +229,7 @@ function getStatusText (statusCode) { case 508: return 'Loop Detected' case 510: return 'Not Extended' case 511: return 'Network Authentication Required' - default: - throw new ReferenceError(`Unknown status code "${statusCode}"!`) + default: return 'unknown' } } diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json index b5b34d1a76b080..763eed020780a2 100644 --- a/deps/undici/src/package.json +++ b/deps/undici/src/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "5.1.1", + "version": "5.2.0", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { @@ -73,21 +73,22 @@ "chai-iterator": "^3.0.2", "chai-string": "^1.5.0", "concurrently": "^7.1.0", - "cronometro": "^0.8.0", + "cronometro": "^1.0.5", "delay": "^5.0.0", "docsify-cli": "^4.4.3", "formdata-node": "^4.3.1", "https-pem": "^2.0.0", "husky": "^7.0.2", + "import-fresh": "^3.3.0", "jest": "^28.0.1", "jsfuzz": "^1.0.15", - "mocha": "^9.1.1", + "mocha": "^10.0.0", "p-timeout": "^3.2.0", "pre-commit": "^1.2.2", "proxy": "^1.0.2", "proxyquire": "^2.1.3", "semver": "^7.3.5", - "sinon": "^13.0.2", + "sinon": "^14.0.0", "snazzy": "^9.0.0", "standard": "^17.0.0", "tap": "^16.1.0", diff --git a/deps/undici/src/types/fetch.d.ts b/deps/undici/src/types/fetch.d.ts index 4a23eabc5033c0..1b8692b251cf11 100644 --- a/deps/undici/src/types/fetch.d.ts +++ b/deps/undici/src/types/fetch.d.ts @@ -7,6 +7,8 @@ import { URL, URLSearchParams } from 'url' import { ReadableStream } from 'stream/web' import { FormData } from './formdata' +import Dispatcher = require('./dispatcher') + export type RequestInfo = string | URL | Request export declare function fetch ( @@ -36,9 +38,21 @@ export interface BodyMixin { readonly text: () => Promise } +export interface HeadersIterator { + next(...args: [] | [TNext]): IteratorResult; +} + +export interface HeadersIterableIterator extends HeadersIterator { + [Symbol.iterator](): HeadersIterableIterator; +} + +export interface HeadersIterable { + [Symbol.iterator](): HeadersIterator; +} + export type HeadersInit = string[][] | Record> | Headers -export declare class Headers implements Iterable<[string, string]> { +export declare class Headers implements HeadersIterable<[string, string]> { constructor (init?: HeadersInit) readonly append: (name: string, value: string) => void readonly delete: (name: string) => void @@ -50,10 +64,10 @@ export declare class Headers implements Iterable<[string, string]> { thisArg?: unknown ) => void - readonly keys: () => IterableIterator - readonly values: () => IterableIterator - readonly entries: () => IterableIterator<[string, string]> - readonly [Symbol.iterator]: () => Iterator<[string, string]> + readonly keys: () => HeadersIterableIterator + readonly values: () => HeadersIterableIterator + readonly entries: () => HeadersIterableIterator<[string, string]> + readonly [Symbol.iterator]: () => HeadersIterator<[string, string]> } export type RequestCache = @@ -99,6 +113,7 @@ export interface RequestInit { readonly referrer?: string readonly referrerPolicy?: ReferrerPolicy readonly window?: null + readonly dispatcher?: Dispatcher } export type ReferrerPolicy = diff --git a/deps/undici/undici.js b/deps/undici/undici.js index 402f38095f29b8..867492229205f4 100644 --- a/deps/undici/undici.js +++ b/deps/undici/undici.js @@ -112,15 +112,6 @@ var require_errors = __commonJS({ this.code = "UND_ERR_RES_CONTENT_LENGTH_MISMATCH"; } }; - var TrailerMismatchError = class extends UndiciError { - constructor(message) { - super(message); - Error.captureStackTrace(this, TrailerMismatchError); - this.name = "TrailerMismatchError"; - this.message = message || "Trailers does not match trailer header"; - this.code = "UND_ERR_TRAILER_MISMATCH"; - } - }; var ClientDestroyedError = class extends UndiciError { constructor(message) { super(message); @@ -185,7 +176,6 @@ var require_errors = __commonJS({ BodyTimeoutError, RequestContentLengthMismatchError, ConnectTimeoutError, - TrailerMismatchError, InvalidArgumentError, InvalidReturnValueError, RequestAbortedError, @@ -2651,7 +2641,6 @@ var require_client = __commonJS({ var { RequestContentLengthMismatchError, ResponseContentLengthMismatchError, - TrailerMismatchError, InvalidArgumentError, RequestAbortedError, HeadersTimeoutError, @@ -2985,7 +2974,6 @@ var require_client = __commonJS({ this.paused = false; this.resume = this.resume.bind(this); this.bytesRead = 0; - this.trailer = ""; this.keepAlive = ""; this.contentLength = ""; } @@ -3133,8 +3121,6 @@ var require_client = __commonJS({ const key = this.headers[len - 2]; if (key.length === 10 && key.toString().toLowerCase() === "keep-alive") { this.keepAlive += buf.toString(); - } else if (key.length === 7 && key.toString().toLowerCase() === "trailer") { - this.trailer += buf.toString(); } else if (key.length === 14 && key.toString().toLowerCase() === "content-length") { this.contentLength += buf.toString(); } @@ -3280,7 +3266,7 @@ var require_client = __commonJS({ } } onMessageComplete() { - const { client, socket, statusCode, upgrade, trailer, headers, contentLength, bytesRead, shouldKeepAlive } = this; + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this; if (socket.destroyed && (!statusCode || shouldKeepAlive)) { return -1; } @@ -3294,7 +3280,6 @@ var require_client = __commonJS({ this.statusText = ""; this.bytesRead = 0; this.contentLength = ""; - this.trailer = ""; this.keepAlive = ""; assert(this.headers.length % 2 === 0); this.headers = []; @@ -3302,22 +3287,6 @@ var require_client = __commonJS({ if (statusCode < 200) { return; } - const trailers = trailer ? trailer.split(/,\s*/) : []; - for (let i = 0; i < trailers.length; i++) { - const trailer2 = trailers[i]; - let found = false; - for (let n = 0; n < headers.length; n += 2) { - const key = headers[n]; - if (key.length === trailer2.length && key.toString().toLowerCase() === trailer2.toLowerCase()) { - found = true; - break; - } - } - if (!found) { - util.destroy(socket, new TrailerMismatchError()); - return -1; - } - } if (request.method !== "HEAD" && contentLength && bytesRead !== parseInt(contentLength, 10)) { util.destroy(socket, new ResponseContentLengthMismatchError()); return -1; @@ -4088,7 +4057,7 @@ var require_agent = __commonJS({ function defaultFactory(origin, opts) { return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } - var Agent2 = class extends DispatcherBase { + var Agent = class extends DispatcherBase { constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { super(); if (typeof factory !== "function") { @@ -4179,7 +4148,38 @@ var require_agent = __commonJS({ await Promise.all(destroyPromises); } }; - module2.exports = Agent2; + module2.exports = Agent; + } +}); + +// lib/global.js +var require_global = __commonJS({ + "lib/global.js"(exports2, module2) { + "use strict"; + var globalDispatcher = Symbol.for("undici.globalDispatcher.1"); + var { InvalidArgumentError } = require_errors(); + var Agent = require_agent(); + if (getGlobalDispatcher2() === void 0) { + setGlobalDispatcher(new Agent()); + } + function setGlobalDispatcher(agent) { + if (!agent || typeof agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument agent must implement Agent"); + } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }); + } + function getGlobalDispatcher2() { + return globalThis[globalDispatcher]; + } + module2.exports = { + setGlobalDispatcher, + getGlobalDispatcher: getGlobalDispatcher2 + }; } }); @@ -4238,6 +4238,20 @@ var require_headers = __commonJS({ throw TypeError(); } } + var esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())); + function makeHeadersIterator(iterator) { + const i = { + next() { + if (Object.getPrototypeOf(this) !== i) { + throw new TypeError("'next' called on an object that does not implement interface Headers Iterator."); + } + return iterator.next(); + }, + [Symbol.toStringTag]: "Headers Iterator" + }; + Object.setPrototypeOf(i, esIteratorPrototype); + return Object.setPrototypeOf({}, i); + } var HeadersList = class { constructor(init) { if (init instanceof HeadersList) { @@ -4301,25 +4315,16 @@ var require_headers = __commonJS({ fill(this, init); } get [Symbol.toStringTag]() { - if (!(this instanceof Headers)) { - throw new TypeError("Illegal invocation"); - } return this.constructor.name; } - toString() { - if (!(this instanceof Headers)) { - throw new TypeError("Illegal invocation"); - } - return Object.prototype.toString.call(this); - } - append(...args) { + append(name, value) { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - if (args.length < 2) { - throw new TypeError(`Failed to execute 'append' on 'Headers': 2 arguments required, but only ${args.length} present.`); + if (arguments.length < 2) { + throw new TypeError(`Failed to execute 'append' on 'Headers': 2 arguments required, but only ${arguments.length} present.`); } - const normalizedName = normalizeAndValidateHeaderName(String(args[0])); + const normalizedName = normalizeAndValidateHeaderName(String(name)); if (this[kGuard] === "immutable") { throw new TypeError("immutable"); } else if (this[kGuard] === "request" && forbiddenHeaderNames.includes(normalizedName)) { @@ -4328,16 +4333,16 @@ var require_headers = __commonJS({ } else if (this[kGuard] === "response" && forbiddenResponseHeaderNames.includes(normalizedName)) { return; } - return this[kHeadersList].append(String(args[0]), String(args[1])); + return this[kHeadersList].append(String(name), String(value)); } - delete(...args) { + delete(name) { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - if (args.length < 1) { - throw new TypeError(`Failed to execute 'delete' on 'Headers': 1 argument required, but only ${args.length} present.`); + if (arguments.length < 1) { + throw new TypeError(`Failed to execute 'delete' on 'Headers': 1 argument required, but only ${arguments.length} present.`); } - const normalizedName = normalizeAndValidateHeaderName(String(args[0])); + const normalizedName = normalizeAndValidateHeaderName(String(name)); if (this[kGuard] === "immutable") { throw new TypeError("immutable"); } else if (this[kGuard] === "request" && forbiddenHeaderNames.includes(normalizedName)) { @@ -4346,42 +4351,42 @@ var require_headers = __commonJS({ } else if (this[kGuard] === "response" && forbiddenResponseHeaderNames.includes(normalizedName)) { return; } - return this[kHeadersList].delete(String(args[0])); + return this[kHeadersList].delete(String(name)); } - get(...args) { + get(name) { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - if (args.length < 1) { - throw new TypeError(`Failed to execute 'get' on 'Headers': 1 argument required, but only ${args.length} present.`); + if (arguments.length < 1) { + throw new TypeError(`Failed to execute 'get' on 'Headers': 1 argument required, but only ${arguments.length} present.`); } - return this[kHeadersList].get(String(args[0])); + return this[kHeadersList].get(String(name)); } - has(...args) { + has(name) { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - if (args.length < 1) { - throw new TypeError(`Failed to execute 'has' on 'Headers': 1 argument required, but only ${args.length} present.`); + if (arguments.length < 1) { + throw new TypeError(`Failed to execute 'has' on 'Headers': 1 argument required, but only ${arguments.length} present.`); } - return this[kHeadersList].has(String(args[0])); + return this[kHeadersList].has(String(name)); } - set(...args) { + set(name, value) { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - if (args.length < 2) { - throw new TypeError(`Failed to execute 'set' on 'Headers': 2 arguments required, but only ${args.length} present.`); + if (arguments.length < 2) { + throw new TypeError(`Failed to execute 'set' on 'Headers': 2 arguments required, but only ${arguments.length} present.`); } if (this[kGuard] === "immutable") { throw new TypeError("immutable"); - } else if (this[kGuard] === "request" && forbiddenHeaderNames.includes(String(args[0]).toLocaleLowerCase())) { + } else if (this[kGuard] === "request" && forbiddenHeaderNames.includes(String(name).toLocaleLowerCase())) { return; } else if (this[kGuard] === "request-no-cors") { - } else if (this[kGuard] === "response" && forbiddenResponseHeaderNames.includes(String(args[0]).toLocaleLowerCase())) { + } else if (this[kGuard] === "response" && forbiddenResponseHeaderNames.includes(String(name).toLocaleLowerCase())) { return; } - return this[kHeadersList].set(String(args[0]), String(args[1])); + return this[kHeadersList].set(String(name), String(value)); } get [kHeadersSortedMap]() { this[kHeadersList][kHeadersSortedMap] ??= new Map([...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1)); @@ -4391,41 +4396,33 @@ var require_headers = __commonJS({ if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - return this[kHeadersSortedMap].keys(); + return makeHeadersIterator(this[kHeadersSortedMap].keys()); } values() { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - return this[kHeadersSortedMap].values(); + return makeHeadersIterator(this[kHeadersSortedMap].values()); } entries() { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - return this[kHeadersSortedMap].entries(); - } - [Symbol.iterator]() { - if (!(this instanceof Headers)) { - throw new TypeError("Illegal invocation"); - } - return this[kHeadersSortedMap]; + return makeHeadersIterator(this[kHeadersSortedMap].entries()); } - forEach(...args) { + forEach(callbackFn, thisArg = globalThis) { if (!(this instanceof Headers)) { throw new TypeError("Illegal invocation"); } - if (args.length < 1) { - throw new TypeError(`Failed to execute 'forEach' on 'Headers': 1 argument required, but only ${args.length} present.`); + if (arguments.length < 1) { + throw new TypeError(`Failed to execute 'forEach' on 'Headers': 1 argument required, but only ${arguments.length} present.`); } - if (typeof args[0] !== "function") { + if (typeof callbackFn !== "function") { throw new TypeError("Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'."); } - const callback = args[0]; - const thisArg = args[1]; - this[kHeadersSortedMap].forEach((value, index) => { - callback.apply(thisArg, [value, index, this]); - }); + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]); + } } [Symbol.for("nodejs.util.inspect.custom")]() { if (!(this instanceof Headers)) { @@ -4977,11 +4974,10 @@ var require_request2 = __commonJS({ } this[kState].headersList = new HeadersList(); this[kHeaders][kHeadersList] = this[kState].headersList; - if (headers instanceof Headers) { - this[kState].headersList = new HeadersList([ - ...this[kState].headersList, - ...headers[kHeadersList] - ]); + if (headers.constructor.name === "Headers") { + for (const [key, val] of headers[kHeadersList] || headers) { + this[kHeaders].append(key, val); + } } else { fillHeaders(this[kState].headersList, headers); } @@ -4996,7 +4992,6 @@ var require_request2 = __commonJS({ initBody = extractedBody; if (contentType && !this[kHeaders].has("content-type")) { this[kHeaders].append("content-type", contentType); - this[kState].headersList.append("content-type", contentType); } } const inputOrInitBody = initBody ?? inputBody; @@ -6221,6 +6216,9 @@ var require_fetch = __commonJS({ let bytes; try { const { done, value } = await fetchParams.controller.next(); + if (isAborted(fetchParams)) { + break; + } bytes = done ? void 0 : value; } catch (err) { if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { @@ -6365,11 +6363,11 @@ var require_fetch = __commonJS({ }); // index-fetch.js -var Agent = require_agent(); -var globalDispatcher = new Agent(); +var { getGlobalDispatcher } = require_global(); var fetchImpl = require_fetch(); module.exports.fetch = async function fetch(resource) { - return fetchImpl.apply(globalDispatcher, arguments); + const dispatcher = arguments[1] && arguments[1].dispatcher || getGlobalDispatcher(); + return fetchImpl.apply(dispatcher, arguments); }; module.exports.FormData = require_formdata().FormData; module.exports.Headers = require_headers().Headers;