diff --git a/deps/undici/src/lib/core/util.js b/deps/undici/src/lib/core/util.js index dfefac6d15cfa5..71071aff47f309 100644 --- a/deps/undici/src/lib/core/util.js +++ b/deps/undici/src/lib/core/util.js @@ -600,20 +600,25 @@ function ReadableStreamFrom (iterable) { async start () { iterator = iterable[Symbol.asyncIterator]() }, - async pull (controller) { - const { done, value } = await iterator.next() - if (done) { - queueMicrotask(() => { - controller.close() - controller.byobRequest?.respond(0) - }) - } else { - const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) - if (buf.byteLength) { - controller.enqueue(new Uint8Array(buf)) + pull (controller) { + async function pull () { + const { done, value } = await iterator.next() + if (done) { + queueMicrotask(() => { + controller.close() + controller.byobRequest?.respond(0) + }) + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) + if (buf.byteLength) { + controller.enqueue(new Uint8Array(buf)) + } else { + return await pull() + } } } - return controller.desiredSize > 0 + + return pull() }, async cancel () { await iterator.return() diff --git a/deps/undici/src/lib/interceptor/dns.js b/deps/undici/src/lib/interceptor/dns.js index c8d56c2cf77562..3828760714350f 100644 --- a/deps/undici/src/lib/interceptor/dns.js +++ b/deps/undici/src/lib/interceptor/dns.js @@ -32,7 +32,7 @@ class DNSInstance { // If full, we just return the origin if (ips == null && this.full) { - cb(null, origin.origin) + cb(null, origin) return } @@ -74,9 +74,9 @@ class DNSInstance { cb( null, - `${origin.protocol}//${ + new URL(`${origin.protocol}//${ ip.family === 6 ? `[${ip.address}]` : ip.address - }${port}` + }${port}`) ) }) } else { @@ -105,9 +105,9 @@ class DNSInstance { cb( null, - `${origin.protocol}//${ + new URL(`${origin.protocol}//${ ip.family === 6 ? `[${ip.address}]` : ip.address - }${port}` + }${port}`) ) } } @@ -192,6 +192,38 @@ class DNSInstance { return ip } + pickFamily (origin, ipFamily) { + const records = this.#records.get(origin.hostname)?.records + if (!records) { + return null + } + + const family = records[ipFamily] + if (!family) { + return null + } + + if (family.offset == null || family.offset === maxInt) { + family.offset = 0 + } else { + family.offset++ + } + + const position = family.offset % family.ips.length + const ip = family.ips[position] ?? null + if (ip == null) { + return ip + } + + if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms + // We delete expired records + // It is possible that they have different TTL, so we manage them individually + family.ips.splice(position, 1) + } + + return ip + } + setRecords (origin, addresses) { const timestamp = Date.now() const records = { records: { 4: null, 6: null } } @@ -228,10 +260,13 @@ class DNSDispatchHandler extends DecoratorHandler { #dispatch = null #origin = null #controller = null + #newOrigin = null + #firstTry = true - constructor (state, { origin, handler, dispatch }, opts) { + constructor (state, { origin, handler, dispatch, newOrigin }, opts) { super(handler) this.#origin = origin + this.#newOrigin = newOrigin this.#opts = { ...opts } this.#state = state this.#dispatch = dispatch @@ -242,21 +277,36 @@ class DNSDispatchHandler extends DecoratorHandler { case 'ETIMEDOUT': case 'ECONNREFUSED': { if (this.#state.dualStack) { - // We delete the record and retry - this.#state.runLookup(this.#origin, this.#opts, (err, newOrigin) => { - if (err) { - super.onResponseError(controller, err) - return - } - - const dispatchOpts = { - ...this.#opts, - origin: newOrigin - } + if (!this.#firstTry) { + super.onResponseError(controller, err) + return + } + this.#firstTry = false + + // Pick an ip address from the other family + const otherFamily = this.#newOrigin.hostname[0] === '[' ? 4 : 6 + const ip = this.#state.pickFamily(this.#origin, otherFamily) + if (ip == null) { + super.onResponseError(controller, err) + return + } - this.#dispatch(dispatchOpts, this) - }) + let port + if (typeof ip.port === 'number') { + port = `:${ip.port}` + } else if (this.#origin.port !== '') { + port = `:${this.#origin.port}` + } else { + port = '' + } + const dispatchOpts = { + ...this.#opts, + origin: `${this.#origin.protocol}//${ + ip.family === 6 ? `[${ip.address}]` : ip.address + }${port}` + } + this.#dispatch(dispatchOpts, this) return } @@ -266,7 +316,8 @@ class DNSDispatchHandler extends DecoratorHandler { } case 'ENOTFOUND': this.#state.deleteRecords(this.#origin) - // eslint-disable-next-line no-fallthrough + super.onResponseError(controller, err) + break default: super.onResponseError(controller, err) break @@ -356,11 +407,10 @@ module.exports = interceptorOpts => { return handler.onResponseError(null, err) } - let dispatchOpts = null - dispatchOpts = { + const dispatchOpts = { ...origDispatchOpts, servername: origin.hostname, // For SNI on TLS - origin: newOrigin, + origin: newOrigin.origin, headers: { host: origin.host, ...origDispatchOpts.headers @@ -369,7 +419,10 @@ module.exports = interceptorOpts => { dispatch( dispatchOpts, - instance.getHandler({ origin, dispatch, handler }, origDispatchOpts) + instance.getHandler( + { origin, dispatch, handler, newOrigin }, + origDispatchOpts + ) ) }) diff --git a/deps/undici/src/lib/llhttp/wasm_build_env.txt b/deps/undici/src/lib/llhttp/wasm_build_env.txt index b921c749fab2ac..7c201f62b6a70f 100644 --- a/deps/undici/src/lib/llhttp/wasm_build_env.txt +++ b/deps/undici/src/lib/llhttp/wasm_build_env.txt @@ -1,5 +1,5 @@ -> undici@7.2.1 build:wasm +> undici@7.2.3 build:wasm > node build/wasm.js --docker > docker run --rm --platform=linux/x86_64 --user 1001:128 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/build/lib/llhttp --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/build,target=/home/node/build/build --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/deps,target=/home/node/build/deps -t ghcr.io/nodejs/wasm-builder@sha256:975f391d907e42a75b8c72eb77c782181e941608687d4d8694c3e9df415a0970 node build/wasm.js diff --git a/deps/undici/src/lib/web/fetch/body.js b/deps/undici/src/lib/web/fetch/body.js index b092b3c83db8b9..850a37fd801be5 100644 --- a/deps/undici/src/lib/web/fetch/body.js +++ b/deps/undici/src/lib/web/fetch/body.js @@ -17,6 +17,14 @@ const { isErrored, isDisturbed } = require('node:stream') const { isArrayBuffer } = require('node:util/types') const { serializeAMimeType } = require('./data-url') const { multipartFormDataParser } = require('./formdata-parser') +let random + +try { + const crypto = require('node:crypto') + random = (max) => crypto.randomInt(0, max) +} catch { + random = (max) => Math.floor(Math.random(max)) +} const textEncoder = new TextEncoder() function noop () {} @@ -110,7 +118,7 @@ function extractBody (object, keepalive = false) { // Set source to a copy of the bytes held by object. source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) } else if (webidl.is.FormData(object)) { - const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}` + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` const prefix = `--${boundary}\r\nContent-Disposition: form-data` /*! formdata-polyfill. MIT License. Jimmy Wärting */ diff --git a/deps/undici/src/lib/web/websocket/connection.js b/deps/undici/src/lib/web/websocket/connection.js index 6ecc53af1795f3..0d0c5801a3ed61 100644 --- a/deps/undici/src/lib/web/websocket/connection.js +++ b/deps/undici/src/lib/web/websocket/connection.js @@ -1,7 +1,7 @@ 'use strict' const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require('./constants') -const { failWebsocketConnection, parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util') +const { parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util') const { channels } = require('../../core/diagnostics') const { makeRequest } = require('../fetch/request') const { fetching } = require('../fetch/index') @@ -294,7 +294,32 @@ function closeWebSocketConnection (object, code, reason, validate = false) { } } +/** + * @param {import('./websocket').Handler} handler + * @param {number} code + * @param {string|undefined} reason + * @returns {void} + */ +function failWebsocketConnection (handler, code, reason) { + // If _The WebSocket Connection is Established_ prior to the point where + // the endpoint is required to _Fail the WebSocket Connection_, the + // endpoint SHOULD send a Close frame with an appropriate status code + // (Section 7.4) before proceeding to _Close the WebSocket Connection_. + if (isEstablished(handler.readyState)) { + closeWebSocketConnection(handler, code, reason, false) + } + + handler.controller.abort() + + if (handler.socket?.destroyed === false) { + handler.socket.destroy() + } + + handler.onFail(code, reason) +} + module.exports = { establishWebSocketConnection, + failWebsocketConnection, closeWebSocketConnection } diff --git a/deps/undici/src/lib/web/websocket/receiver.js b/deps/undici/src/lib/web/websocket/receiver.js index 3f5bc544b7fa90..3ea603e4858d8b 100644 --- a/deps/undici/src/lib/web/websocket/receiver.js +++ b/deps/undici/src/lib/web/websocket/receiver.js @@ -7,13 +7,13 @@ const { channels } = require('../../core/diagnostics') const { isValidStatusCode, isValidOpcode, - failWebsocketConnection, websocketMessageReceived, utf8Decode, isControlFrame, isTextBinaryFrame, isContinuationFrame } = require('./util') +const { failWebsocketConnection } = require('./connection') const { WebsocketFrameSend } = require('./frame') const { PerMessageDeflate } = require('./permessage-deflate') diff --git a/deps/undici/src/lib/web/websocket/stream/websocketstream.js b/deps/undici/src/lib/web/websocket/stream/websocketstream.js index 71d63a5767a3e7..c44183dd8b55aa 100644 --- a/deps/undici/src/lib/web/websocket/stream/websocketstream.js +++ b/deps/undici/src/lib/web/websocket/stream/websocketstream.js @@ -3,8 +3,8 @@ const { createDeferredPromise, environmentSettingsObject } = require('../../fetch/util') const { states, opcodes, sentCloseFrameState } = require('../constants') const { webidl } = require('../../fetch/webidl') -const { getURLRecord, isValidSubprotocol, isEstablished, failWebsocketConnection, utf8Decode } = require('../util') -const { establishWebSocketConnection, closeWebSocketConnection } = require('../connection') +const { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require('../util') +const { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = require('../connection') const { types } = require('node:util') const { channels } = require('../../../core/diagnostics') const { WebsocketFrameSend } = require('../frame') diff --git a/deps/undici/src/lib/web/websocket/util.js b/deps/undici/src/lib/web/websocket/util.js index 45e74498568456..3e9c5479043ed7 100644 --- a/deps/undici/src/lib/web/websocket/util.js +++ b/deps/undici/src/lib/web/websocket/util.js @@ -156,32 +156,6 @@ function isValidStatusCode (code) { return code >= 3000 && code <= 4999 } -/** - * @param {import('./websocket').Handler} handler - * @param {number} code - * @param {string|undefined} reason - * @returns {void} - */ -function failWebsocketConnection (handler, code, reason) { - // If _The WebSocket Connection is Established_ prior to the point where - // the endpoint is required to _Fail the WebSocket Connection_, the - // endpoint SHOULD send a Close frame with an appropriate status code - // (Section 7.4) before proceeding to _Close the WebSocket Connection_. - if (isEstablished(handler.readyState)) { - // avoid circular require - performance is not important here - const { closeWebSocketConnection } = require('./connection') - closeWebSocketConnection(handler, code, reason, false) - } - - handler.controller.abort() - - if (handler.socket?.destroyed === false) { - handler.socket.destroy() - } - - handler.onFail(code, reason) -} - /** * @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.5 * @param {number} opcode @@ -350,7 +324,6 @@ module.exports = { fireEvent, isValidSubprotocol, isValidStatusCode, - failWebsocketConnection, websocketMessageReceived, utf8Decode, isControlFrame, diff --git a/deps/undici/src/lib/web/websocket/websocket.js b/deps/undici/src/lib/web/websocket/websocket.js index 63bf67c6f8e349..651eadd32f9125 100644 --- a/deps/undici/src/lib/web/websocket/websocket.js +++ b/deps/undici/src/lib/web/websocket/websocket.js @@ -10,12 +10,11 @@ const { isClosing, isValidSubprotocol, fireEvent, - failWebsocketConnection, utf8Decode, toArrayBuffer, getURLRecord } = require('./util') -const { establishWebSocketConnection, closeWebSocketConnection } = require('./connection') +const { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = require('./connection') const { ByteParser } = require('./receiver') const { kEnumerableProperty } = require('../../core/util') const { getGlobalDispatcher } = require('../../global') diff --git a/deps/undici/src/package-lock.json b/deps/undici/src/package-lock.json index 17428ee198e8fe..c9d37efcbf8855 100644 --- a/deps/undici/src/package-lock.json +++ b/deps/undici/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "undici", - "version": "7.2.1", + "version": "7.2.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "undici", - "version": "7.2.1", + "version": "7.2.3", "license": "MIT", "devDependencies": { "@fastify/busboy": "3.1.1", @@ -578,9 +578,9 @@ } }, "node_modules/@bcoe/v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.1.tgz", - "integrity": "sha512-W+a0/JpU28AqH4IKtwUPcEUnUyXMDLALcn5/JLczGGT9fHE2sIby/xP/oQnx3nxkForzgzPy201RAKcB4xPAFQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", "dev": true, "license": "MIT", "engines": { @@ -2095,9 +2095,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "18.19.70", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.70.tgz", - "integrity": "sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ==", + "version": "18.19.71", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.71.tgz", + "integrity": "sha512-evXpcgtZm8FY4jqBSN8+DmOTcVkkvTmAayeo4Wf3m1xAruyVGzGuDh/Fb/WWX2yLItUiho42ozyJjB0dw//Tkw==", "dev": true, "license": "MIT", "dependencies": { @@ -2146,17 +2146,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz", - "integrity": "sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", + "integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.19.1", - "@typescript-eslint/type-utils": "8.19.1", - "@typescript-eslint/utils": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", + "@typescript-eslint/scope-manager": "8.20.0", + "@typescript-eslint/type-utils": "8.20.0", + "@typescript-eslint/utils": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2176,16 +2176,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.1.tgz", - "integrity": "sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz", + "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.19.1", - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/typescript-estree": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", + "@typescript-eslint/scope-manager": "8.20.0", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/typescript-estree": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0", "debug": "^4.3.4" }, "engines": { @@ -2201,14 +2201,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.1.tgz", - "integrity": "sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", + "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1" + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2219,14 +2219,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.1.tgz", - "integrity": "sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz", + "integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.19.1", - "@typescript-eslint/utils": "8.19.1", + "@typescript-eslint/typescript-estree": "8.20.0", + "@typescript-eslint/utils": "8.20.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, @@ -2243,9 +2243,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", - "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", + "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", "dev": true, "license": "MIT", "engines": { @@ -2257,14 +2257,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", - "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", + "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2323,16 +2323,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.1.tgz", - "integrity": "sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", + "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.19.1", - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/typescript-estree": "8.19.1" + "@typescript-eslint/scope-manager": "8.20.0", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/typescript-estree": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2347,13 +2347,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", - "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", + "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/types": "8.20.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3724,9 +3724,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.80", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", - "integrity": "sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==", + "version": "1.5.83", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.83.tgz", + "integrity": "sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ==", "dev": true, "license": "ISC" }, @@ -3889,9 +3889,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", "dependencies": { @@ -4411,9 +4411,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.3.tgz", - "integrity": "sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA==", + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8833,9 +8833,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "dev": true, "license": "CC0-1.0" }, @@ -9476,15 +9476,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.1.tgz", - "integrity": "sha512-LKPUQpdEMVOeKluHi8md7rwLcoXHhwvWp3x+sJkMuq3gGm9yaYJtPo8sRZSblMFJ5pcOGCAak/scKf1mvZDlQw==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.20.0.tgz", + "integrity": "sha512-Kxz2QRFsgbWj6Xcftlw3Dd154b3cEPFqQC+qMZrMypSijPd4UanKKvoKDrJ4o8AIfZFKAF+7sMaEIR8mTElozA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.19.1", - "@typescript-eslint/parser": "8.19.1", - "@typescript-eslint/utils": "8.19.1" + "@typescript-eslint/eslint-plugin": "8.20.0", + "@typescript-eslint/parser": "8.20.0", + "@typescript-eslint/utils": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -9518,9 +9518,9 @@ } }, "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "version": "5.28.5", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", + "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json index 95cb149f0d1dc9..fce2115da7fea6 100644 --- a/deps/undici/src/package.json +++ b/deps/undici/src/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "7.2.1", + "version": "7.2.3", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { diff --git a/deps/undici/undici.js b/deps/undici/undici.js index caf0e5247cbd82..5b8ec925ed0be0 100644 --- a/deps/undici/undici.js +++ b/deps/undici/undici.js @@ -1130,20 +1130,25 @@ var require_util = __commonJS({ async start() { iterator = iterable[Symbol.asyncIterator](); }, - async pull(controller) { - const { done, value } = await iterator.next(); - if (done) { - queueMicrotask(() => { - controller.close(); - controller.byobRequest?.respond(0); - }); - } else { - const buf = Buffer.isBuffer(value) ? value : Buffer.from(value); - if (buf.byteLength) { - controller.enqueue(new Uint8Array(buf)); + pull(controller) { + async function pull() { + const { done, value } = await iterator.next(); + if (done) { + queueMicrotask(() => { + controller.close(); + controller.byobRequest?.respond(0); + }); + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value); + if (buf.byteLength) { + controller.enqueue(new Uint8Array(buf)); + } else { + return await pull(); + } } } - return controller.desiredSize > 0; + __name(pull, "pull"); + return pull(); }, async cancel() { await iterator.return(); @@ -5963,6 +5968,13 @@ var require_body = __commonJS({ var { isArrayBuffer } = require("node:util/types"); var { serializeAMimeType } = require_data_url(); var { multipartFormDataParser } = require_formdata_parser(); + var random; + try { + const crypto = require("node:crypto"); + random = /* @__PURE__ */ __name((max) => crypto.randomInt(0, max), "random"); + } catch { + random = /* @__PURE__ */ __name((max) => Math.floor(Math.random(max)), "random"); + } var textEncoder = new TextEncoder(); function noop() { } @@ -6013,7 +6025,7 @@ var require_body = __commonJS({ } else if (ArrayBuffer.isView(object)) { source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)); } else if (webidl.is.FormData(object)) { - const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, "0")}`; + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, "0")}`; const prefix = `--${boundary}\r Content-Disposition: form-data`; const escape = /* @__PURE__ */ __name((str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"), "escape"); @@ -12170,6 +12182,195 @@ var require_constants4 = __commonJS({ } }); +// lib/web/websocket/util.js +var require_util3 = __commonJS({ + "lib/web/websocket/util.js"(exports2, module2) { + "use strict"; + var { states, opcodes } = require_constants4(); + var { isUtf8 } = require("node:buffer"); + var { collectASequenceOfCodePointsFast, removeHTTPWhitespace } = require_data_url(); + function isConnecting(readyState) { + return readyState === states.CONNECTING; + } + __name(isConnecting, "isConnecting"); + function isEstablished(readyState) { + return readyState === states.OPEN; + } + __name(isEstablished, "isEstablished"); + function isClosing(readyState) { + return readyState === states.CLOSING; + } + __name(isClosing, "isClosing"); + function isClosed(readyState) { + return readyState === states.CLOSED; + } + __name(isClosed, "isClosed"); + function fireEvent(e, target, eventFactory = (type, init) => new Event(type, init), eventInitDict = {}) { + const event = eventFactory(e, eventInitDict); + target.dispatchEvent(event); + } + __name(fireEvent, "fireEvent"); + function websocketMessageReceived(handler, type, data) { + handler.onMessage(type, data); + } + __name(websocketMessageReceived, "websocketMessageReceived"); + function toArrayBuffer(buffer) { + if (buffer.byteLength === buffer.buffer.byteLength) { + return buffer.buffer; + } + return new Uint8Array(buffer).buffer; + } + __name(toArrayBuffer, "toArrayBuffer"); + function isValidSubprotocol(protocol) { + if (protocol.length === 0) { + return false; + } + for (let i = 0; i < protocol.length; ++i) { + const code = protocol.charCodeAt(i); + if (code < 33 || // CTL, contains SP (0x20) and HT (0x09) + code > 126 || code === 34 || // " + code === 40 || // ( + code === 41 || // ) + code === 44 || // , + code === 47 || // / + code === 58 || // : + code === 59 || // ; + code === 60 || // < + code === 61 || // = + code === 62 || // > + code === 63 || // ? + code === 64 || // @ + code === 91 || // [ + code === 92 || // \ + code === 93 || // ] + code === 123 || // { + code === 125) { + return false; + } + } + return true; + } + __name(isValidSubprotocol, "isValidSubprotocol"); + function isValidStatusCode(code) { + if (code >= 1e3 && code < 1015) { + return code !== 1004 && // reserved + code !== 1005 && // "MUST NOT be set as a status code" + code !== 1006; + } + return code >= 3e3 && code <= 4999; + } + __name(isValidStatusCode, "isValidStatusCode"); + function isControlFrame(opcode) { + return opcode === opcodes.CLOSE || opcode === opcodes.PING || opcode === opcodes.PONG; + } + __name(isControlFrame, "isControlFrame"); + function isContinuationFrame(opcode) { + return opcode === opcodes.CONTINUATION; + } + __name(isContinuationFrame, "isContinuationFrame"); + function isTextBinaryFrame(opcode) { + return opcode === opcodes.TEXT || opcode === opcodes.BINARY; + } + __name(isTextBinaryFrame, "isTextBinaryFrame"); + function isValidOpcode(opcode) { + return isTextBinaryFrame(opcode) || isContinuationFrame(opcode) || isControlFrame(opcode); + } + __name(isValidOpcode, "isValidOpcode"); + function parseExtensions(extensions) { + const position = { position: 0 }; + const extensionList = /* @__PURE__ */ new Map(); + while (position.position < extensions.length) { + const pair = collectASequenceOfCodePointsFast(";", extensions, position); + const [name, value = ""] = pair.split("="); + extensionList.set( + removeHTTPWhitespace(name, true, false), + removeHTTPWhitespace(value, false, true) + ); + position.position++; + } + return extensionList; + } + __name(parseExtensions, "parseExtensions"); + function isValidClientWindowBits(value) { + for (let i = 0; i < value.length; i++) { + const byte = value.charCodeAt(i); + if (byte < 48 || byte > 57) { + return false; + } + } + return true; + } + __name(isValidClientWindowBits, "isValidClientWindowBits"); + function getURLRecord(url, baseURL) { + let urlRecord; + try { + urlRecord = new URL(url, baseURL); + } catch (e) { + throw new DOMException(e, "SyntaxError"); + } + if (urlRecord.protocol === "http:") { + urlRecord.protocol = "ws:"; + } else if (urlRecord.protocol === "https:") { + urlRecord.protocol = "wss:"; + } + if (urlRecord.protocol !== "ws:" && urlRecord.protocol !== "wss:") { + throw new DOMException("expected a ws: or wss: url", "SyntaxError"); + } + if (urlRecord.hash.length || urlRecord.href.endsWith("#")) { + throw new DOMException("hash", "SyntaxError"); + } + return urlRecord; + } + __name(getURLRecord, "getURLRecord"); + function validateCloseCodeAndReason(code, reason) { + if (code !== null) { + if (code !== 1e3 && (code < 3e3 || code > 4999)) { + throw new DOMException("invalid code", "InvalidAccessError"); + } + } + if (reason !== null) { + const reasonBytesLength = Buffer.byteLength(reason); + if (reasonBytesLength > 123) { + throw new DOMException(`Reason must be less than 123 bytes; received ${reasonBytesLength}`, "SyntaxError"); + } + } + } + __name(validateCloseCodeAndReason, "validateCloseCodeAndReason"); + var utf8Decode = (() => { + if (typeof process.versions.icu === "string") { + const fatalDecoder = new TextDecoder("utf-8", { fatal: true }); + return fatalDecoder.decode.bind(fatalDecoder); + } + return function(buffer) { + if (isUtf8(buffer)) { + return buffer.toString("utf-8"); + } + throw new TypeError("Invalid utf-8 received."); + }; + })(); + module2.exports = { + isConnecting, + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isContinuationFrame, + isTextBinaryFrame, + isValidOpcode, + parseExtensions, + isValidClientWindowBits, + toArrayBuffer, + getURLRecord, + validateCloseCodeAndReason + }; + } +}); + // lib/web/websocket/frame.js var require_frame = __commonJS({ "lib/web/websocket/frame.js"(exports2, module2) { @@ -12289,7 +12490,7 @@ var require_connection = __commonJS({ "lib/web/websocket/connection.js"(exports2, module2) { "use strict"; var { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require_constants4(); - var { failWebsocketConnection, parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require_util3(); + var { parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require_util3(); var { channels } = require_diagnostics(); var { makeRequest } = require_request2(); var { fetching } = require_fetch(); @@ -12425,94 +12626,8 @@ var require_connection = __commonJS({ } } __name(closeWebSocketConnection, "closeWebSocketConnection"); - module2.exports = { - establishWebSocketConnection, - closeWebSocketConnection - }; - } -}); - -// lib/web/websocket/util.js -var require_util3 = __commonJS({ - "lib/web/websocket/util.js"(exports2, module2) { - "use strict"; - var { states, opcodes } = require_constants4(); - var { isUtf8 } = require("node:buffer"); - var { collectASequenceOfCodePointsFast, removeHTTPWhitespace } = require_data_url(); - function isConnecting(readyState) { - return readyState === states.CONNECTING; - } - __name(isConnecting, "isConnecting"); - function isEstablished(readyState) { - return readyState === states.OPEN; - } - __name(isEstablished, "isEstablished"); - function isClosing(readyState) { - return readyState === states.CLOSING; - } - __name(isClosing, "isClosing"); - function isClosed(readyState) { - return readyState === states.CLOSED; - } - __name(isClosed, "isClosed"); - function fireEvent(e, target, eventFactory = (type, init) => new Event(type, init), eventInitDict = {}) { - const event = eventFactory(e, eventInitDict); - target.dispatchEvent(event); - } - __name(fireEvent, "fireEvent"); - function websocketMessageReceived(handler, type, data) { - handler.onMessage(type, data); - } - __name(websocketMessageReceived, "websocketMessageReceived"); - function toArrayBuffer(buffer) { - if (buffer.byteLength === buffer.buffer.byteLength) { - return buffer.buffer; - } - return new Uint8Array(buffer).buffer; - } - __name(toArrayBuffer, "toArrayBuffer"); - function isValidSubprotocol(protocol) { - if (protocol.length === 0) { - return false; - } - for (let i = 0; i < protocol.length; ++i) { - const code = protocol.charCodeAt(i); - if (code < 33 || // CTL, contains SP (0x20) and HT (0x09) - code > 126 || code === 34 || // " - code === 40 || // ( - code === 41 || // ) - code === 44 || // , - code === 47 || // / - code === 58 || // : - code === 59 || // ; - code === 60 || // < - code === 61 || // = - code === 62 || // > - code === 63 || // ? - code === 64 || // @ - code === 91 || // [ - code === 92 || // \ - code === 93 || // ] - code === 123 || // { - code === 125) { - return false; - } - } - return true; - } - __name(isValidSubprotocol, "isValidSubprotocol"); - function isValidStatusCode(code) { - if (code >= 1e3 && code < 1015) { - return code !== 1004 && // reserved - code !== 1005 && // "MUST NOT be set as a status code" - code !== 1006; - } - return code >= 3e3 && code <= 4999; - } - __name(isValidStatusCode, "isValidStatusCode"); function failWebsocketConnection(handler, code, reason) { if (isEstablished(handler.readyState)) { - const { closeWebSocketConnection } = require_connection(); closeWebSocketConnection(handler, code, reason, false); } handler.controller.abort(); @@ -12522,114 +12637,10 @@ var require_util3 = __commonJS({ handler.onFail(code, reason); } __name(failWebsocketConnection, "failWebsocketConnection"); - function isControlFrame(opcode) { - return opcode === opcodes.CLOSE || opcode === opcodes.PING || opcode === opcodes.PONG; - } - __name(isControlFrame, "isControlFrame"); - function isContinuationFrame(opcode) { - return opcode === opcodes.CONTINUATION; - } - __name(isContinuationFrame, "isContinuationFrame"); - function isTextBinaryFrame(opcode) { - return opcode === opcodes.TEXT || opcode === opcodes.BINARY; - } - __name(isTextBinaryFrame, "isTextBinaryFrame"); - function isValidOpcode(opcode) { - return isTextBinaryFrame(opcode) || isContinuationFrame(opcode) || isControlFrame(opcode); - } - __name(isValidOpcode, "isValidOpcode"); - function parseExtensions(extensions) { - const position = { position: 0 }; - const extensionList = /* @__PURE__ */ new Map(); - while (position.position < extensions.length) { - const pair = collectASequenceOfCodePointsFast(";", extensions, position); - const [name, value = ""] = pair.split("="); - extensionList.set( - removeHTTPWhitespace(name, true, false), - removeHTTPWhitespace(value, false, true) - ); - position.position++; - } - return extensionList; - } - __name(parseExtensions, "parseExtensions"); - function isValidClientWindowBits(value) { - for (let i = 0; i < value.length; i++) { - const byte = value.charCodeAt(i); - if (byte < 48 || byte > 57) { - return false; - } - } - return true; - } - __name(isValidClientWindowBits, "isValidClientWindowBits"); - function getURLRecord(url, baseURL) { - let urlRecord; - try { - urlRecord = new URL(url, baseURL); - } catch (e) { - throw new DOMException(e, "SyntaxError"); - } - if (urlRecord.protocol === "http:") { - urlRecord.protocol = "ws:"; - } else if (urlRecord.protocol === "https:") { - urlRecord.protocol = "wss:"; - } - if (urlRecord.protocol !== "ws:" && urlRecord.protocol !== "wss:") { - throw new DOMException("expected a ws: or wss: url", "SyntaxError"); - } - if (urlRecord.hash.length || urlRecord.href.endsWith("#")) { - throw new DOMException("hash", "SyntaxError"); - } - return urlRecord; - } - __name(getURLRecord, "getURLRecord"); - function validateCloseCodeAndReason(code, reason) { - if (code !== null) { - if (code !== 1e3 && (code < 3e3 || code > 4999)) { - throw new DOMException("invalid code", "InvalidAccessError"); - } - } - if (reason !== null) { - const reasonBytesLength = Buffer.byteLength(reason); - if (reasonBytesLength > 123) { - throw new DOMException(`Reason must be less than 123 bytes; received ${reasonBytesLength}`, "SyntaxError"); - } - } - } - __name(validateCloseCodeAndReason, "validateCloseCodeAndReason"); - var utf8Decode = (() => { - if (typeof process.versions.icu === "string") { - const fatalDecoder = new TextDecoder("utf-8", { fatal: true }); - return fatalDecoder.decode.bind(fatalDecoder); - } - return function(buffer) { - if (isUtf8(buffer)) { - return buffer.toString("utf-8"); - } - throw new TypeError("Invalid utf-8 received."); - }; - })(); module2.exports = { - isConnecting, - isEstablished, - isClosing, - isClosed, - fireEvent, - isValidSubprotocol, - isValidStatusCode, + establishWebSocketConnection, failWebsocketConnection, - websocketMessageReceived, - utf8Decode, - isControlFrame, - isContinuationFrame, - isTextBinaryFrame, - isValidOpcode, - parseExtensions, - isValidClientWindowBits, - toArrayBuffer, - getURLRecord, - validateCloseCodeAndReason + closeWebSocketConnection }; } }); @@ -12703,13 +12714,13 @@ var require_receiver = __commonJS({ var { isValidStatusCode, isValidOpcode, - failWebsocketConnection, websocketMessageReceived, utf8Decode, isControlFrame, isTextBinaryFrame, isContinuationFrame } = require_util3(); + var { failWebsocketConnection } = require_connection(); var { WebsocketFrameSend } = require_frame(); var { PerMessageDeflate } = require_permessage_deflate(); var ByteParser = class extends Writable { @@ -13122,12 +13133,11 @@ var require_websocket = __commonJS({ isClosing, isValidSubprotocol, fireEvent, - failWebsocketConnection, utf8Decode, toArrayBuffer, getURLRecord } = require_util3(); - var { establishWebSocketConnection, closeWebSocketConnection } = require_connection(); + var { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = require_connection(); var { ByteParser } = require_receiver(); var { kEnumerableProperty } = require_util(); var { getGlobalDispatcher: getGlobalDispatcher2 } = require_global2(); diff --git a/src/undici_version.h b/src/undici_version.h index 6295756809ea68..681d698a513f8c 100644 --- a/src/undici_version.h +++ b/src/undici_version.h @@ -2,5 +2,5 @@ // Refer to tools/dep_updaters/update-undici.sh #ifndef SRC_UNDICI_VERSION_H_ #define SRC_UNDICI_VERSION_H_ -#define UNDICI_VERSION "7.2.1" +#define UNDICI_VERSION "7.2.3" #endif // SRC_UNDICI_VERSION_H_