diff --git a/dist/index.js b/dist/index.js index 02a207875b..f3fb562b77 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13700,7 +13700,7 @@ if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env } } -function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { +function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) { if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') } @@ -13718,7 +13718,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...o servername = servername || options.servername || util.getServerName(host) || null const sessionKey = servername || hostname - const session = sessionCache.get(sessionKey) || null + const session = customSession || sessionCache.get(sessionKey) || null assert(sessionKey) @@ -14419,7 +14419,8 @@ const { isBlobLike, buildURL, validateHandler, - getServerName + getServerName, + normalizedMethodRecords } = __nccwpck_require__(3983) const { channels } = __nccwpck_require__(8438) const { headerNameLowerCasedRecord } = __nccwpck_require__(4462) @@ -14454,13 +14455,13 @@ class Request { method !== 'CONNECT' ) { throw new InvalidArgumentError('path must be an absolute URL or start with a slash') - } else if (invalidPathRegex.exec(path) !== null) { + } else if (invalidPathRegex.test(path)) { throw new InvalidArgumentError('invalid request path') } if (typeof method !== 'string') { throw new InvalidArgumentError('method must be a string') - } else if (!isValidHTTPToken(method)) { + } else if (normalizedMethodRecords[method] === undefined && !isValidHTTPToken(method)) { throw new InvalidArgumentError('invalid request method') } @@ -15684,6 +15685,31 @@ function errorRequest (client, request, err) { const kEnumerableProperty = Object.create(null) kEnumerableProperty.enumerable = true +const normalizedMethodRecordsBase = { + delete: 'DELETE', + DELETE: 'DELETE', + get: 'GET', + GET: 'GET', + head: 'HEAD', + HEAD: 'HEAD', + options: 'OPTIONS', + OPTIONS: 'OPTIONS', + post: 'POST', + POST: 'POST', + put: 'PUT', + PUT: 'PUT' +} + +const normalizedMethodRecords = { + ...normalizedMethodRecordsBase, + patch: 'patch', + PATCH: 'PATCH' +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(normalizedMethodRecordsBase, null) +Object.setPrototypeOf(normalizedMethodRecords, null) + module.exports = { kEnumerableProperty, nop, @@ -15722,6 +15748,8 @@ module.exports = { isValidHeaderValue, isTokenCharCode, parseRangeHeader, + normalizedMethodRecordsBase, + normalizedMethodRecords, isValidPort, isHttpOrHttpsPrefixed, nodeMajor, @@ -17052,19 +17080,19 @@ function writeH1 (client, request) { /* istanbul ignore else: assertion */ if (!body || bodyLength === 0) { - writeBuffer({ abort, body: null, client, request, socket, contentLength, header, expectsPayload }) + writeBuffer(abort, null, client, request, socket, contentLength, header, expectsPayload) } else if (util.isBuffer(body)) { - writeBuffer({ abort, body, client, request, socket, contentLength, header, expectsPayload }) + writeBuffer(abort, body, client, request, socket, contentLength, header, expectsPayload) } else if (util.isBlobLike(body)) { if (typeof body.stream === 'function') { - writeIterable({ abort, body: body.stream(), client, request, socket, contentLength, header, expectsPayload }) + writeIterable(abort, body.stream(), client, request, socket, contentLength, header, expectsPayload) } else { - writeBlob({ abort, body, client, request, socket, contentLength, header, expectsPayload }) + writeBlob(abort, body, client, request, socket, contentLength, header, expectsPayload) } } else if (util.isStream(body)) { - writeStream({ abort, body, client, request, socket, contentLength, header, expectsPayload }) + writeStream(abort, body, client, request, socket, contentLength, header, expectsPayload) } else if (util.isIterable(body)) { - writeIterable({ abort, body, client, request, socket, contentLength, header, expectsPayload }) + writeIterable(abort, body, client, request, socket, contentLength, header, expectsPayload) } else { assert(false) } @@ -17072,7 +17100,7 @@ function writeH1 (client, request) { return true } -function writeStream ({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { +function writeStream (abort, body, client, request, socket, contentLength, header, expectsPayload) { assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') let finished = false @@ -17175,7 +17203,7 @@ function writeStream ({ abort, body, client, request, socket, contentLength, hea } } -function writeBuffer ({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { +function writeBuffer (abort, body, client, request, socket, contentLength, header, expectsPayload) { try { if (!body) { if (contentLength === 0) { @@ -17205,7 +17233,7 @@ function writeBuffer ({ abort, body, client, request, socket, contentLength, hea } } -async function writeBlob ({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { +async function writeBlob (abort, body, client, request, socket, contentLength, header, expectsPayload) { assert(contentLength === body.size, 'blob body must have content length') try { @@ -17233,7 +17261,7 @@ async function writeBlob ({ abort, body, client, request, socket, contentLength, } } -async function writeIterable ({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { +async function writeIterable (abort, body, client, request, socket, contentLength, header, expectsPayload) { assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') let callback = null @@ -17906,82 +17934,80 @@ function writeH2 (client, request) { function writeBodyH2 () { /* istanbul ignore else: assertion */ if (!body || contentLength === 0) { - writeBuffer({ + writeBuffer( abort, + stream, + null, client, request, + client[kSocket], contentLength, - expectsPayload, - h2stream: stream, - body: null, - socket: client[kSocket] - }) + expectsPayload + ) } else if (util.isBuffer(body)) { - writeBuffer({ + writeBuffer( abort, + stream, + body, client, request, + client[kSocket], contentLength, - body, - expectsPayload, - h2stream: stream, - socket: client[kSocket] - }) + expectsPayload + ) } else if (util.isBlobLike(body)) { if (typeof body.stream === 'function') { - writeIterable({ + writeIterable( abort, + stream, + body.stream(), client, request, + client[kSocket], contentLength, - expectsPayload, - h2stream: stream, - body: body.stream(), - socket: client[kSocket] - }) + expectsPayload + ) } else { - writeBlob({ + writeBlob( abort, + stream, body, client, request, + client[kSocket], contentLength, - expectsPayload, - h2stream: stream, - socket: client[kSocket] - }) + expectsPayload + ) } } else if (util.isStream(body)) { - writeStream({ + writeStream( abort, + client[kSocket], + expectsPayload, + stream, body, client, request, - contentLength, - expectsPayload, - socket: client[kSocket], - h2stream: stream, - header: '' - }) + contentLength + ) } else if (util.isIterable(body)) { - writeIterable({ + writeIterable( abort, + stream, body, client, request, + client[kSocket], contentLength, - expectsPayload, - header: '', - h2stream: stream, - socket: client[kSocket] - }) + expectsPayload + ) } else { assert(false) } } } -function writeBuffer ({ abort, h2stream, body, client, request, socket, contentLength, expectsPayload }) { +function writeBuffer (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { try { if (body != null && util.isBuffer(body)) { assert(contentLength === body.byteLength, 'buffer body must have content length') @@ -18004,7 +18030,7 @@ function writeBuffer ({ abort, h2stream, body, client, request, socket, contentL } } -function writeStream ({ abort, socket, expectsPayload, h2stream, body, client, request, contentLength }) { +function writeStream (abort, socket, expectsPayload, h2stream, body, client, request, contentLength) { assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') // For HTTP/2, is enough to pipe the stream @@ -18035,7 +18061,7 @@ function writeStream ({ abort, socket, expectsPayload, h2stream, body, client, r } } -async function writeBlob ({ abort, h2stream, body, client, request, socket, contentLength, expectsPayload }) { +async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { assert(contentLength === body.size, 'blob body must have content length') try { @@ -18063,7 +18089,7 @@ async function writeBlob ({ abort, h2stream, body, client, request, socket, cont } } -async function writeIterable ({ abort, h2stream, body, client, request, socket, contentLength, expectsPayload }) { +async function writeIterable (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) { assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') let callback = null @@ -20439,7 +20465,7 @@ class RetryHandler { this.abort( new RequestRetryError('Content-Range mismatch', statusCode, { headers, - count: this.retryCount + data: { count: this.retryCount } }) ) return false @@ -20450,7 +20476,7 @@ class RetryHandler { this.abort( new RequestRetryError('ETag mismatch', statusCode, { headers, - count: this.retryCount + data: { count: this.retryCount } }) ) return false @@ -25463,7 +25489,7 @@ function bodyMixinMethods (instance) { // Return a Blob whose contents are bytes and type attribute // is mimeType. return new Blob([bytes], { type: mimeType }) - }, instance, false) + }, instance) }, arrayBuffer () { @@ -25472,21 +25498,20 @@ function bodyMixinMethods (instance) { // given a byte sequence bytes: return a new ArrayBuffer // whose contents are bytes. return consumeBody(this, (bytes) => { - // Note: arrayBuffer already cloned. - return bytes.buffer - }, instance, true) + return new Uint8Array(bytes).buffer + }, instance) }, text () { // The text() method steps are to return the result of running // consume body with this and UTF-8 decode. - return consumeBody(this, utf8DecodeBytes, instance, false) + return consumeBody(this, utf8DecodeBytes, instance) }, json () { // The json() method steps are to return the result of running // consume body with this and parse JSON from bytes. - return consumeBody(this, parseJSONFromBytes, instance, false) + return consumeBody(this, parseJSONFromBytes, instance) }, formData () { @@ -25538,7 +25563,7 @@ function bodyMixinMethods (instance) { throw new TypeError( 'Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".' ) - }, instance, false) + }, instance) }, bytes () { @@ -25546,8 +25571,8 @@ function bodyMixinMethods (instance) { // with this and the following step given a byte sequence bytes: return the // result of creating a Uint8Array from bytes in this’s relevant realm. return consumeBody(this, (bytes) => { - return new Uint8Array(bytes.buffer, 0, bytes.byteLength) - }, instance, true) + return new Uint8Array(bytes) + }, instance) } } @@ -25563,9 +25588,8 @@ function mixinBody (prototype) { * @param {Response|Request} object * @param {(value: unknown) => unknown} convertBytesToJSValue * @param {Response|Request} instance - * @param {boolean} [shouldClone] */ -async function consumeBody (object, convertBytesToJSValue, instance, shouldClone) { +async function consumeBody (object, convertBytesToJSValue, instance) { webidl.brandCheck(object, instance) // 1. If object is unusable, then return a promise rejected @@ -25603,7 +25627,7 @@ async function consumeBody (object, convertBytesToJSValue, instance, shouldClone // 6. Otherwise, fully read object’s body given successSteps, // errorSteps, and object’s relevant global object. - await fullyReadBody(object[kState].body, successSteps, errorSteps, shouldClone) + await fullyReadBody(object[kState].body, successSteps, errorSteps) // 7. Return promise. return promise.promise @@ -30470,9 +30494,7 @@ const nodeUtil = __nccwpck_require__(7261) const { isValidHTTPToken, sameOrigin, - normalizeMethod, - environmentSettingsObject, - normalizeMethodRecord + environmentSettingsObject } = __nccwpck_require__(1310) const { forbiddenMethodsSet, @@ -30484,7 +30506,7 @@ const { requestCache, requestDuplex } = __nccwpck_require__(8160) -const { kEnumerableProperty } = util +const { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util const { kHeaders, kSignal, kState, kDispatcher } = __nccwpck_require__(749) const { webidl } = __nccwpck_require__(4890) const { URLSerializer } = __nccwpck_require__(7704) @@ -30809,7 +30831,7 @@ class Request { // 1. Let method be init["method"]. let method = init.method - const mayBeNormalized = normalizeMethodRecord[method] + const mayBeNormalized = normalizedMethodRecords[method] if (mayBeNormalized !== undefined) { // Note: Bypass validation DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH and these lowercase ones @@ -30821,12 +30843,16 @@ class Request { throw new TypeError(`'${method}' is not a valid HTTP method.`) } - if (forbiddenMethodsSet.has(method.toUpperCase())) { + const upperCase = method.toUpperCase() + + if (forbiddenMethodsSet.has(upperCase)) { throw new TypeError(`'${method}' HTTP method is unsupported.`) } // 3. Normalize method. - method = normalizeMethod(method) + // https://fetch.spec.whatwg.org/#concept-method-normalize + // Note: must be in uppercase + method = normalizedMethodRecordsBase[upperCase] ?? method // 4. Set request’s method to method. request.method = method @@ -32146,7 +32172,7 @@ const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet const { getGlobalOrigin } = __nccwpck_require__(2850) const { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = __nccwpck_require__(7704) const { performance } = __nccwpck_require__(8846) -const { isBlobLike, ReadableStreamFrom, isValidHTTPToken } = __nccwpck_require__(3983) +const { isBlobLike, ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = __nccwpck_require__(3983) const assert = __nccwpck_require__(8061) const { isUint8Array } = __nccwpck_require__(3746) const { webidl } = __nccwpck_require__(4890) @@ -32400,10 +32426,13 @@ function appendRequestOriginHeader (request) { // TODO: implement "byte-serializing a request origin" let serializedOrigin = request.origin - // "'client' is changed to an origin during fetching." - // This doesn't happen in undici (in most cases) because undici, by default, - // has no concept of origin. - if (serializedOrigin === 'client') { + // - "'client' is changed to an origin during fetching." + // This doesn't happen in undici (in most cases) because undici, by default, + // has no concept of origin. + // - request.origin can also be set to request.client.origin (client being + // an environment settings object), which is undefined without using + // setGlobalOrigin. + if (serializedOrigin === 'client' || serializedOrigin === undefined) { return } @@ -32931,37 +32960,12 @@ function isCancelled (fetchParams) { fetchParams.controller.state === 'terminated' } -const normalizeMethodRecordBase = { - delete: 'DELETE', - DELETE: 'DELETE', - get: 'GET', - GET: 'GET', - head: 'HEAD', - HEAD: 'HEAD', - options: 'OPTIONS', - OPTIONS: 'OPTIONS', - post: 'POST', - POST: 'POST', - put: 'PUT', - PUT: 'PUT' -} - -const normalizeMethodRecord = { - ...normalizeMethodRecordBase, - patch: 'patch', - PATCH: 'PATCH' -} - -// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. -Object.setPrototypeOf(normalizeMethodRecordBase, null) -Object.setPrototypeOf(normalizeMethodRecord, null) - /** * @see https://fetch.spec.whatwg.org/#concept-method-normalize * @param {string} method */ function normalizeMethod (method) { - return normalizeMethodRecordBase[method.toLowerCase()] ?? method + return normalizedMethodRecordsBase[method.toLowerCase()] ?? method } // https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string @@ -33191,7 +33195,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde /** * @see https://fetch.spec.whatwg.org/#body-fully-read */ -async function fullyReadBody (body, processBody, processBodyError, shouldClone) { +async function fullyReadBody (body, processBody, processBodyError) { // 1. If taskDestination is null, then set taskDestination to // the result of starting a new parallel queue. @@ -33217,7 +33221,7 @@ async function fullyReadBody (body, processBody, processBodyError, shouldClone) // 5. Read all bytes from reader, given successSteps and errorSteps. try { - successSteps(await readAllBytes(reader, shouldClone)) + successSteps(await readAllBytes(reader)) } catch (e) { errorSteps(e) } @@ -33265,9 +33269,8 @@ function isomorphicEncode (input) { * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes * @see https://streams.spec.whatwg.org/#read-loop * @param {ReadableStreamDefaultReader} reader - * @param {boolean} [shouldClone] */ -async function readAllBytes (reader, shouldClone) { +async function readAllBytes (reader) { const bytes = [] let byteLength = 0 @@ -33276,13 +33279,6 @@ async function readAllBytes (reader, shouldClone) { if (done) { // 1. Call successSteps with bytes. - if (bytes.length === 1) { - const { buffer, byteOffset, byteLength } = bytes[0] - if (shouldClone === false) { - return Buffer.from(buffer, byteOffset, byteLength) - } - return Buffer.from(buffer.slice(byteOffset, byteOffset + byteLength), 0, byteLength) - } return Buffer.concat(bytes, byteLength) } @@ -33779,7 +33775,6 @@ module.exports = { urlHasHttpsScheme, urlIsHttpHttpsScheme, readAllBytes, - normalizeMethodRecord, simpleRangeHeaderValue, buildContentRange, parseMetadata, @@ -37535,8 +37530,6 @@ const { types } = __nccwpck_require__(7261) const { ErrorEvent, CloseEvent } = __nccwpck_require__(5033) const { SendQueue } = __nccwpck_require__(4821) -let experimentalWarned = false - // https://websockets.spec.whatwg.org/#interface-definition class WebSocket extends EventTarget { #events = { @@ -37563,13 +37556,6 @@ class WebSocket extends EventTarget { const prefix = 'WebSocket constructor' webidl.argumentLengthCheck(arguments, 1, prefix) - if (!experimentalWarned) { - experimentalWarned = true - process.emitWarning('WebSockets are experimental, expect them to change at any time.', { - code: 'UNDICI-WS' - }) - } - const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols, prefix, 'options') url = webidl.converters.USVString(url, prefix, 'url')