mirror of
https://github.com/nodejs/node.git
synced 2025-04-28 21:46:48 +00:00
deps: update undici to 7.8.0
PR-URL: https://github.com/nodejs/node/pull/57770 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Matthew Aitken <maitken033380023@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
parent
afd318db67
commit
e273ddf7a4
2
deps/undici/src/docs/docs/api/Dispatcher.md
vendored
2
deps/undici/src/docs/docs/api/Dispatcher.md
vendored
@ -194,7 +194,7 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
|
||||
* **method** `string`
|
||||
* **reset** `boolean` (optional) - Default: `false` - If `false`, the request will attempt to create a long-living connection by sending the `connection: keep-alive` header,otherwise will attempt to close it immediately after response by sending `connection: close` within the request and closing the socket afterwards.
|
||||
* **body** `string | Buffer | Uint8Array | stream.Readable | Iterable | AsyncIterable | null` (optional) - Default: `null`
|
||||
* **headers** `UndiciHeaders | string[]` (optional) - Default: `null`.
|
||||
* **headers** `UndiciHeaders` (optional) - Default: `null`.
|
||||
* **query** `Record<string, any> | null` (optional) - Default: `null` - Query string params to be embedded in the request URL. Note that both keys and values of query are encoded using `encodeURIComponent`. If for some reason you need to send them unencoded, embed query params into path directly instead.
|
||||
* **idempotent** `boolean` (optional) - Default: `true` if `method` is `'HEAD'` or `'GET'` - Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline has completed.
|
||||
* **blocking** `boolean` (optional) - Default: `method !== 'HEAD'` - Whether the response is expected to take a long time and would end up blocking the pipeline. When this is set to `true` further pipelining will be avoided on the same connection until headers have been received.
|
||||
|
262
deps/undici/src/docs/docs/api/H2CClient.md
vendored
Normal file
262
deps/undici/src/docs/docs/api/H2CClient.md
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
# Class: H2CClient
|
||||
|
||||
Extends: `undici.Dispatcher`
|
||||
|
||||
A basic H2C client.
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
const { createServer } = require('node:http2')
|
||||
const { once } = require('node:events')
|
||||
const { H2CClient } = require('undici')
|
||||
|
||||
const server = createServer((req, res) => {
|
||||
res.writeHead(200)
|
||||
res.end('Hello, world!')
|
||||
})
|
||||
|
||||
server.listen()
|
||||
once(server, 'listening').then(() => {
|
||||
const client = new H2CClient(`http://localhost:${server.address().port}/`)
|
||||
|
||||
const response = await client.request({ path: '/', method: 'GET' })
|
||||
console.log(response.statusCode) // 200
|
||||
response.body.text.then((text) => {
|
||||
console.log(text) // Hello, world!
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## `new H2CClient(url[, options])`
|
||||
|
||||
Arguments:
|
||||
|
||||
- **url** `URL | string` - Should only include the **protocol, hostname, and port**. It only supports `http` protocol.
|
||||
- **options** `H2CClientOptions` (optional)
|
||||
|
||||
Returns: `H2CClient`
|
||||
|
||||
### Parameter: `H2CClientOptions`
|
||||
|
||||
- **bodyTimeout** `number | null` (optional) - Default: `300e3` - The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use `0` to disable it entirely. Defaults to 300 seconds. Please note the `timeout` will be reset if you keep writing data to the socket everytime.
|
||||
- **headersTimeout** `number | null` (optional) - Default: `300e3` - The amount of time, in milliseconds, the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds.
|
||||
- **keepAliveMaxTimeout** `number | null` (optional) - Default: `600e3` - The maximum allowed `keepAliveTimeout`, in milliseconds, when overridden by _keep-alive_ hints from the server. Defaults to 10 minutes.
|
||||
- **keepAliveTimeout** `number | null` (optional) - Default: `4e3` - The timeout, in milliseconds, after which a socket without active requests will time out. Monitors time between activity on a connected socket. This value may be overridden by _keep-alive_ hints from the server. See [MDN: HTTP - Headers - Keep-Alive directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive#directives) for more details. Defaults to 4 seconds.
|
||||
- **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `2e3` - A number of milliseconds subtracted from server _keep-alive_ hints when overriding `keepAliveTimeout` to account for timing inaccuracies caused by e.g. transport latency. Defaults to 2 seconds.
|
||||
- **maxHeaderSize** `number | null` (optional) - Default: `--max-http-header-size` or `16384` - The maximum length of request headers in bytes. Defaults to Node.js' --max-http-header-size or 16KiB.
|
||||
- **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable.
|
||||
- **maxConcurrentStreams**: `number` - Default: `100`. Dictates the maximum number of concurrent streams for a single H2 session. It can be overridden by a SETTINGS remote frame.
|
||||
- **pipelining** `number | null` (optional) - Default to `maxConcurrentStreams` - The amount of concurrent requests sent over a single HTTP/2 session in accordance with [RFC-7540](https://httpwg.org/specs/rfc7540.html#StreamsLayer) Stream specification. Streams can be closed up by remote server at any time.
|
||||
- **connect** `ConnectOptions | null` (optional) - Default: `null`.
|
||||
- **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body.
|
||||
- **autoSelectFamily**: `boolean` (optional) - Default: depends on local Node version, on Node 18.13.0 and above is `false`. Enables a family autodetection algorithm that loosely implements section 5 of [RFC 8305](https://tools.ietf.org/html/rfc8305#section-5). See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details. This option is ignored if not supported by the current Node version.
|
||||
- **autoSelectFamilyAttemptTimeout**: `number` - Default: depends on local Node version, on Node 18.13.0 and above is `250`. The amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details.
|
||||
|
||||
#### Parameter: `H2CConnectOptions`
|
||||
|
||||
- **socketPath** `string | null` (optional) - Default: `null` - An IPC endpoint, either Unix domain socket or Windows named pipe.
|
||||
- **timeout** `number | null` (optional) - In milliseconds, Default `10e3`.
|
||||
- **servername** `string | null` (optional)
|
||||
- **keepAlive** `boolean | null` (optional) - Default: `true` - TCP keep-alive enabled
|
||||
- **keepAliveInitialDelay** `number | null` (optional) - Default: `60000` - TCP keep-alive interval for the socket in milliseconds
|
||||
|
||||
### Example - Basic Client instantiation
|
||||
|
||||
This will instantiate the undici H2CClient, but it will not connect to the origin until something is queued. Consider using `client.connect` to prematurely connect to the origin, or just call `client.request`.
|
||||
|
||||
```js
|
||||
"use strict";
|
||||
import { H2CClient } from "undici";
|
||||
|
||||
const client = new H2CClient("http://localhost:3000");
|
||||
```
|
||||
|
||||
## Instance Methods
|
||||
|
||||
### `H2CClient.close([callback])`
|
||||
|
||||
Implements [`Dispatcher.close([callback])`](/docs/docs/api/Dispatcher.md#dispatcherclosecallback-promise).
|
||||
|
||||
### `H2CClient.destroy([error, callback])`
|
||||
|
||||
Implements [`Dispatcher.destroy([error, callback])`](/docs/docs/api/Dispatcher.md#dispatcherdestroyerror-callback-promise).
|
||||
|
||||
Waits until socket is closed before invoking the callback (or returning a promise if no callback is provided).
|
||||
|
||||
### `H2CClient.connect(options[, callback])`
|
||||
|
||||
See [`Dispatcher.connect(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback).
|
||||
|
||||
### `H2CClient.dispatch(options, handlers)`
|
||||
|
||||
Implements [`Dispatcher.dispatch(options, handlers)`](/docs/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler).
|
||||
|
||||
### `H2CClient.pipeline(options, handler)`
|
||||
|
||||
See [`Dispatcher.pipeline(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler).
|
||||
|
||||
### `H2CClient.request(options[, callback])`
|
||||
|
||||
See [`Dispatcher.request(options [, callback])`](/docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback).
|
||||
|
||||
### `H2CClient.stream(options, factory[, callback])`
|
||||
|
||||
See [`Dispatcher.stream(options, factory[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback).
|
||||
|
||||
### `H2CClient.upgrade(options[, callback])`
|
||||
|
||||
See [`Dispatcher.upgrade(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback).
|
||||
|
||||
## Instance Properties
|
||||
|
||||
### `H2CClient.closed`
|
||||
|
||||
- `boolean`
|
||||
|
||||
`true` after `H2CClient.close()` has been called.
|
||||
|
||||
### `H2CClient.destroyed`
|
||||
|
||||
- `boolean`
|
||||
|
||||
`true` after `client.destroyed()` has been called or `client.close()` has been called and the client shutdown has completed.
|
||||
|
||||
### `H2CClient.pipelining`
|
||||
|
||||
- `number`
|
||||
|
||||
Property to get and set the pipelining factor.
|
||||
|
||||
## Instance Events
|
||||
|
||||
### Event: `'connect'`
|
||||
|
||||
See [Dispatcher Event: `'connect'`](/docs/docs/api/Dispatcher.md#event-connect).
|
||||
|
||||
Parameters:
|
||||
|
||||
- **origin** `URL`
|
||||
- **targets** `Array<Dispatcher>`
|
||||
|
||||
Emitted when a socket has been created and connected. The client will connect once `client.size > 0`.
|
||||
|
||||
#### Example - Client connect event
|
||||
|
||||
```js
|
||||
import { createServer } from "node:http2";
|
||||
import { H2CClient } from "undici";
|
||||
import { once } from "events";
|
||||
|
||||
const server = createServer((request, response) => {
|
||||
response.end("Hello, World!");
|
||||
}).listen();
|
||||
|
||||
await once(server, "listening");
|
||||
|
||||
const client = new H2CClient(`http://localhost:${server.address().port}`);
|
||||
|
||||
client.on("connect", (origin) => {
|
||||
console.log(`Connected to ${origin}`); // should print before the request body statement
|
||||
});
|
||||
|
||||
try {
|
||||
const { body } = await client.request({
|
||||
path: "/",
|
||||
method: "GET",
|
||||
});
|
||||
body.setEncoding("utf-8");
|
||||
body.on("data", console.log);
|
||||
client.close();
|
||||
server.close();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
client.close();
|
||||
server.close();
|
||||
}
|
||||
```
|
||||
|
||||
### Event: `'disconnect'`
|
||||
|
||||
See [Dispatcher Event: `'disconnect'`](/docs/docs/api/Dispatcher.md#event-disconnect).
|
||||
|
||||
Parameters:
|
||||
|
||||
- **origin** `URL`
|
||||
- **targets** `Array<Dispatcher>`
|
||||
- **error** `Error`
|
||||
|
||||
Emitted when socket has disconnected. The error argument of the event is the error which caused the socket to disconnect. The client will reconnect if or once `client.size > 0`.
|
||||
|
||||
#### Example - Client disconnect event
|
||||
|
||||
```js
|
||||
import { createServer } from "node:http2";
|
||||
import { H2CClient } from "undici";
|
||||
import { once } from "events";
|
||||
|
||||
const server = createServer((request, response) => {
|
||||
response.destroy();
|
||||
}).listen();
|
||||
|
||||
await once(server, "listening");
|
||||
|
||||
const client = new H2CClient(`http://localhost:${server.address().port}`);
|
||||
|
||||
client.on("disconnect", (origin) => {
|
||||
console.log(`Disconnected from ${origin}`);
|
||||
});
|
||||
|
||||
try {
|
||||
await client.request({
|
||||
path: "/",
|
||||
method: "GET",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
client.close();
|
||||
server.close();
|
||||
}
|
||||
```
|
||||
|
||||
### Event: `'drain'`
|
||||
|
||||
Emitted when pipeline is no longer busy.
|
||||
|
||||
See [Dispatcher Event: `'drain'`](/docs/docs/api/Dispatcher.md#event-drain).
|
||||
|
||||
#### Example - Client drain event
|
||||
|
||||
```js
|
||||
import { createServer } from "node:http2";
|
||||
import { H2CClient } from "undici";
|
||||
import { once } from "events";
|
||||
|
||||
const server = createServer((request, response) => {
|
||||
response.end("Hello, World!");
|
||||
}).listen();
|
||||
|
||||
await once(server, "listening");
|
||||
|
||||
const client = new H2CClient(`http://localhost:${server.address().port}`);
|
||||
|
||||
client.on("drain", () => {
|
||||
console.log("drain event");
|
||||
client.close();
|
||||
server.close();
|
||||
});
|
||||
|
||||
const requests = [
|
||||
client.request({ path: "/", method: "GET" }),
|
||||
client.request({ path: "/", method: "GET" }),
|
||||
client.request({ path: "/", method: "GET" }),
|
||||
];
|
||||
|
||||
await Promise.all(requests);
|
||||
|
||||
console.log("requests completed");
|
||||
```
|
||||
|
||||
### Event: `'error'`
|
||||
|
||||
Invoked for users errors such as throwing in the `onError` handler.
|
2
deps/undici/src/docs/docs/api/MockAgent.md
vendored
2
deps/undici/src/docs/docs/api/MockAgent.md
vendored
@ -477,7 +477,7 @@ This method returns any pending interceptors registered on a mock agent. A pendi
|
||||
|
||||
Returns: `PendingInterceptor[]` (where `PendingInterceptor` is a `MockDispatch` with an additional `origin: string`)
|
||||
|
||||
#### Example - List all pending inteceptors
|
||||
#### Example - List all pending interceptors
|
||||
|
||||
```js
|
||||
const agent = new MockAgent()
|
||||
|
2
deps/undici/src/index.js
vendored
2
deps/undici/src/index.js
vendored
@ -8,6 +8,7 @@ const Agent = require('./lib/dispatcher/agent')
|
||||
const ProxyAgent = require('./lib/dispatcher/proxy-agent')
|
||||
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
|
||||
const RetryAgent = require('./lib/dispatcher/retry-agent')
|
||||
const H2CClient = require('./lib/dispatcher/h2c-client')
|
||||
const errors = require('./lib/core/errors')
|
||||
const util = require('./lib/core/util')
|
||||
const { InvalidArgumentError } = errors
|
||||
@ -33,6 +34,7 @@ module.exports.Agent = Agent
|
||||
module.exports.ProxyAgent = ProxyAgent
|
||||
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
|
||||
module.exports.RetryAgent = RetryAgent
|
||||
module.exports.H2CClient = H2CClient
|
||||
module.exports.RetryHandler = RetryHandler
|
||||
|
||||
module.exports.DecoratorHandler = DecoratorHandler
|
||||
|
12
deps/undici/src/lib/cache/sqlite-cache-store.js
vendored
12
deps/undici/src/lib/cache/sqlite-cache-store.js
vendored
@ -115,6 +115,11 @@ module.exports = class SqliteCacheStore {
|
||||
this.#db = new DatabaseSync(opts?.location ?? ':memory:')
|
||||
|
||||
this.#db.exec(`
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA synchronous = NORMAL;
|
||||
PRAGMA temp_store = memory;
|
||||
PRAGMA optimize;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION} (
|
||||
-- Data specific to us
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -134,9 +139,8 @@ module.exports = class SqliteCacheStore {
|
||||
staleAt INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_url ON cacheInterceptorV${VERSION}(url);
|
||||
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_method ON cacheInterceptorV${VERSION}(method);
|
||||
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteAt ON cacheInterceptorV${VERSION}(deleteAt);
|
||||
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_getValuesQuery ON cacheInterceptorV${VERSION}(url, method, deleteAt);
|
||||
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteByUrlQuery ON cacheInterceptorV${VERSION}(deleteAt);
|
||||
`)
|
||||
|
||||
this.#getValuesQuery = this.#db.prepare(`
|
||||
@ -346,7 +350,7 @@ module.exports = class SqliteCacheStore {
|
||||
}
|
||||
|
||||
#prune () {
|
||||
if (this.size <= this.#maxCount) {
|
||||
if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
80
deps/undici/src/lib/core/connect.js
vendored
80
deps/undici/src/lib/core/connect.js
vendored
@ -3,10 +3,7 @@
|
||||
const net = require('node:net')
|
||||
const assert = require('node:assert')
|
||||
const util = require('./util')
|
||||
const { InvalidArgumentError, ConnectTimeoutError } = require('./errors')
|
||||
const timers = require('../util/timers')
|
||||
|
||||
function noop () {}
|
||||
const { InvalidArgumentError } = require('./errors')
|
||||
|
||||
let tls // include tls conditionally since it is not always available
|
||||
|
||||
@ -106,7 +103,6 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
|
||||
servername,
|
||||
session,
|
||||
localAddress,
|
||||
// TODO(HTTP/2): Add support for h2c
|
||||
ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'],
|
||||
socket: httpSocket, // upgrade socket connection
|
||||
port,
|
||||
@ -138,7 +134,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
|
||||
socket.setKeepAlive(true, keepAliveInitialDelay)
|
||||
}
|
||||
|
||||
const clearConnectTimeout = setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port })
|
||||
const clearConnectTimeout = util.setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port })
|
||||
|
||||
socket
|
||||
.setNoDelay(true)
|
||||
@ -165,76 +161,4 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {WeakRef<net.Socket>} socketWeakRef
|
||||
* @param {object} opts
|
||||
* @param {number} opts.timeout
|
||||
* @param {string} opts.hostname
|
||||
* @param {number} opts.port
|
||||
* @returns {() => void}
|
||||
*/
|
||||
const setupConnectTimeout = process.platform === 'win32'
|
||||
? (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop
|
||||
}
|
||||
|
||||
let s1 = null
|
||||
let s2 = null
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
// setImmediate is added to make sure that we prioritize socket error events over timeouts
|
||||
s1 = setImmediate(() => {
|
||||
// Windows needs an extra setImmediate probably due to implementation differences in the socket logic
|
||||
s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts))
|
||||
})
|
||||
}, opts.timeout)
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer)
|
||||
clearImmediate(s1)
|
||||
clearImmediate(s2)
|
||||
}
|
||||
}
|
||||
: (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop
|
||||
}
|
||||
|
||||
let s1 = null
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
// setImmediate is added to make sure that we prioritize socket error events over timeouts
|
||||
s1 = setImmediate(() => {
|
||||
onConnectTimeout(socketWeakRef.deref(), opts)
|
||||
})
|
||||
}, opts.timeout)
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer)
|
||||
clearImmediate(s1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {net.Socket} socket
|
||||
* @param {object} opts
|
||||
* @param {number} opts.timeout
|
||||
* @param {string} opts.hostname
|
||||
* @param {number} opts.port
|
||||
*/
|
||||
function onConnectTimeout (socket, opts) {
|
||||
// The socket could be already garbage collected
|
||||
if (socket == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let message = 'Connect Timeout Error'
|
||||
if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
|
||||
message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(', ')},`
|
||||
} else {
|
||||
message += ` (attempted address: ${opts.hostname}:${opts.port},`
|
||||
}
|
||||
|
||||
message += ` timeout: ${opts.timeout}ms)`
|
||||
|
||||
util.destroy(socket, new ConnectTimeoutError(message))
|
||||
}
|
||||
|
||||
module.exports = buildConnector
|
||||
|
80
deps/undici/src/lib/core/util.js
vendored
80
deps/undici/src/lib/core/util.js
vendored
@ -9,7 +9,8 @@ const { Blob } = require('node:buffer')
|
||||
const nodeUtil = require('node:util')
|
||||
const { stringify } = require('node:querystring')
|
||||
const { EventEmitter: EE } = require('node:events')
|
||||
const { InvalidArgumentError } = require('./errors')
|
||||
const timers = require('../util/timers')
|
||||
const { InvalidArgumentError, ConnectTimeoutError } = require('./errors')
|
||||
const { headerNameLowerCasedRecord } = require('./constants')
|
||||
const { tree } = require('./tree')
|
||||
|
||||
@ -28,6 +29,8 @@ class BodyAsyncIterable {
|
||||
}
|
||||
}
|
||||
|
||||
function noop () {}
|
||||
|
||||
/**
|
||||
* @param {*} body
|
||||
* @returns {*}
|
||||
@ -837,6 +840,78 @@ function errorRequest (client, request, err) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {WeakRef<net.Socket>} socketWeakRef
|
||||
* @param {object} opts
|
||||
* @param {number} opts.timeout
|
||||
* @param {string} opts.hostname
|
||||
* @param {number} opts.port
|
||||
* @returns {() => void}
|
||||
*/
|
||||
const setupConnectTimeout = process.platform === 'win32'
|
||||
? (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop
|
||||
}
|
||||
|
||||
let s1 = null
|
||||
let s2 = null
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
// setImmediate is added to make sure that we prioritize socket error events over timeouts
|
||||
s1 = setImmediate(() => {
|
||||
// Windows needs an extra setImmediate probably due to implementation differences in the socket logic
|
||||
s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts))
|
||||
})
|
||||
}, opts.timeout)
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer)
|
||||
clearImmediate(s1)
|
||||
clearImmediate(s2)
|
||||
}
|
||||
}
|
||||
: (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop
|
||||
}
|
||||
|
||||
let s1 = null
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
// setImmediate is added to make sure that we prioritize socket error events over timeouts
|
||||
s1 = setImmediate(() => {
|
||||
onConnectTimeout(socketWeakRef.deref(), opts)
|
||||
})
|
||||
}, opts.timeout)
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer)
|
||||
clearImmediate(s1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {net.Socket} socket
|
||||
* @param {object} opts
|
||||
* @param {number} opts.timeout
|
||||
* @param {string} opts.hostname
|
||||
* @param {number} opts.port
|
||||
*/
|
||||
function onConnectTimeout (socket, opts) {
|
||||
// The socket could be already garbage collected
|
||||
if (socket == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let message = 'Connect Timeout Error'
|
||||
if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
|
||||
message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(', ')},`
|
||||
} else {
|
||||
message += ` (attempted address: ${opts.hostname}:${opts.port},`
|
||||
}
|
||||
|
||||
message += ` timeout: ${opts.timeout}ms)`
|
||||
|
||||
destroy(socket, new ConnectTimeoutError(message))
|
||||
}
|
||||
|
||||
const kEnumerableProperty = Object.create(null)
|
||||
kEnumerableProperty.enumerable = true
|
||||
|
||||
@ -908,5 +983,6 @@ module.exports = {
|
||||
nodeMajor,
|
||||
nodeMinor,
|
||||
safeHTTPMethods: Object.freeze(['GET', 'HEAD', 'OPTIONS', 'TRACE']),
|
||||
wrapRequestBody
|
||||
wrapRequestBody,
|
||||
setupConnectTimeout
|
||||
}
|
||||
|
1
deps/undici/src/lib/dispatcher/client-h2.js
vendored
1
deps/undici/src/lib/dispatcher/client-h2.js
vendored
@ -208,6 +208,7 @@ function onHttp2SessionGoAway (errorCode) {
|
||||
assert(client[kRunning] === 0)
|
||||
|
||||
client.emit('disconnect', client[kUrl], [client], err)
|
||||
client.emit('connectionError', client[kUrl], [client], err)
|
||||
|
||||
client[kResume]()
|
||||
}
|
||||
|
122
deps/undici/src/lib/dispatcher/h2c-client.js
vendored
Normal file
122
deps/undici/src/lib/dispatcher/h2c-client.js
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
'use strict'
|
||||
const { connect } = require('node:net')
|
||||
|
||||
const { kClose, kDestroy } = require('../core/symbols')
|
||||
const { InvalidArgumentError } = require('../core/errors')
|
||||
const util = require('../core/util')
|
||||
|
||||
const Client = require('./client')
|
||||
const DispatcherBase = require('./dispatcher-base')
|
||||
|
||||
class H2CClient extends DispatcherBase {
|
||||
#client = null
|
||||
|
||||
constructor (origin, clientOpts) {
|
||||
super()
|
||||
|
||||
if (typeof origin === 'string') {
|
||||
origin = new URL(origin)
|
||||
}
|
||||
|
||||
if (origin.protocol !== 'http:') {
|
||||
throw new InvalidArgumentError(
|
||||
'h2c-client: Only h2c protocol is supported'
|
||||
)
|
||||
}
|
||||
|
||||
const { connect, maxConcurrentStreams, pipelining, ...opts } =
|
||||
clientOpts ?? {}
|
||||
let defaultMaxConcurrentStreams = 100
|
||||
let defaultPipelining = 100
|
||||
|
||||
if (
|
||||
maxConcurrentStreams != null &&
|
||||
Number.isInteger(maxConcurrentStreams) &&
|
||||
maxConcurrentStreams > 0
|
||||
) {
|
||||
defaultMaxConcurrentStreams = maxConcurrentStreams
|
||||
}
|
||||
|
||||
if (pipelining != null && Number.isInteger(pipelining) && pipelining > 0) {
|
||||
defaultPipelining = pipelining
|
||||
}
|
||||
|
||||
if (defaultPipelining > defaultMaxConcurrentStreams) {
|
||||
throw new InvalidArgumentError(
|
||||
'h2c-client: pipelining cannot be greater than maxConcurrentStreams'
|
||||
)
|
||||
}
|
||||
|
||||
this.#client = new Client(origin, {
|
||||
...opts,
|
||||
connect: this.#buildConnector(connect),
|
||||
maxConcurrentStreams: defaultMaxConcurrentStreams,
|
||||
pipelining: defaultPipelining,
|
||||
allowH2: true
|
||||
})
|
||||
}
|
||||
|
||||
#buildConnector (connectOpts) {
|
||||
return (opts, callback) => {
|
||||
const timeout = connectOpts?.connectOpts ?? 10e3
|
||||
const { hostname, port, pathname } = opts
|
||||
const socket = connect({
|
||||
...opts,
|
||||
host: hostname,
|
||||
port,
|
||||
pathname
|
||||
})
|
||||
|
||||
// Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket
|
||||
if (opts.keepAlive == null || opts.keepAlive) {
|
||||
const keepAliveInitialDelay =
|
||||
opts.keepAliveInitialDelay == null ? 60e3 : opts.keepAliveInitialDelay
|
||||
socket.setKeepAlive(true, keepAliveInitialDelay)
|
||||
}
|
||||
|
||||
socket.alpnProtocol = 'h2'
|
||||
|
||||
const clearConnectTimeout = util.setupConnectTimeout(
|
||||
new WeakRef(socket),
|
||||
{ timeout, hostname, port }
|
||||
)
|
||||
|
||||
socket
|
||||
.setNoDelay(true)
|
||||
.once('connect', function () {
|
||||
queueMicrotask(clearConnectTimeout)
|
||||
|
||||
if (callback) {
|
||||
const cb = callback
|
||||
callback = null
|
||||
cb(null, this)
|
||||
}
|
||||
})
|
||||
.on('error', function (err) {
|
||||
queueMicrotask(clearConnectTimeout)
|
||||
|
||||
if (callback) {
|
||||
const cb = callback
|
||||
callback = null
|
||||
cb(err)
|
||||
}
|
||||
})
|
||||
|
||||
return socket
|
||||
}
|
||||
}
|
||||
|
||||
dispatch (opts, handler) {
|
||||
return this.#client.dispatch(opts, handler)
|
||||
}
|
||||
|
||||
async [kClose] () {
|
||||
await this.#client.close()
|
||||
}
|
||||
|
||||
async [kDestroy] () {
|
||||
await this.#client.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = H2CClient
|
@ -1,5 +1,5 @@
|
||||
|
||||
> undici@7.6.0 build:wasm
|
||||
> undici@7.8.0 build:wasm
|
||||
> node build/wasm.js --docker
|
||||
|
||||
> docker run --rm --platform=linux/x86_64 --user 1001:118 --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
|
||||
|
592
deps/undici/src/package-lock.json
generated
vendored
592
deps/undici/src/package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
6
deps/undici/src/package.json
vendored
6
deps/undici/src/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "undici",
|
||||
"version": "7.6.0",
|
||||
"version": "7.8.0",
|
||||
"description": "An HTTP/1.1 client, written from scratch for Node.js",
|
||||
"homepage": "https://undici.nodejs.org",
|
||||
"bugs": {
|
||||
@ -80,7 +80,7 @@
|
||||
"test:fuzzing": "node test/fuzzing/fuzzing.test.js",
|
||||
"test:fetch": "npm run build:node && borp --timeout 180000 --expose-gc --concurrency 1 -p \"test/fetch/*.js\" && npm run test:webidl && npm run test:busboy",
|
||||
"test:h2": "npm run test:h2:core && npm run test:h2:fetch",
|
||||
"test:h2:core": "borp -p \"test/http2*.js\"",
|
||||
"test:h2:core": "borp -p \"test/+(http2|h2)*.js\"",
|
||||
"test:h2:fetch": "npm run build:node && borp -p \"test/fetch/http2*.js\"",
|
||||
"test:interceptors": "borp -p \"test/interceptors/*.js\"",
|
||||
"test:jest": "cross-env NODE_V8_COVERAGE= jest",
|
||||
@ -116,7 +116,7 @@
|
||||
"c8": "^10.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"dns-packet": "^5.4.0",
|
||||
"esbuild": "^0.24.0",
|
||||
"esbuild": "^0.25.2",
|
||||
"eslint": "^9.9.0",
|
||||
"fast-check": "^3.17.1",
|
||||
"https-pem": "^3.0.0",
|
||||
|
8
deps/undici/src/types/dispatcher.d.ts
vendored
8
deps/undici/src/types/dispatcher.d.ts
vendored
@ -12,6 +12,8 @@ type AbortSignal = unknown
|
||||
|
||||
export default Dispatcher
|
||||
|
||||
export type UndiciHeaders = Record<string, string | string[]> | IncomingHttpHeaders | string[] | Iterable<[string, string | string[] | undefined]> | null
|
||||
|
||||
/** Dispatcher is the core API used to dispatch requests. */
|
||||
declare class Dispatcher extends EventEmitter {
|
||||
/** Dispatches a request. This API is expected to evolve through semver-major versions and is less stable than the preceding higher level APIs. It is primarily intended for library developers who implement higher level APIs on top of this. */
|
||||
@ -103,7 +105,7 @@ declare namespace Dispatcher {
|
||||
/** Default: `null` */
|
||||
body?: string | Buffer | Uint8Array | Readable | null | FormData;
|
||||
/** Default: `null` */
|
||||
headers?: Record<string, string | string[]> | IncomingHttpHeaders | string[] | Iterable<[string, string | string[] | undefined]> | null;
|
||||
headers?: UndiciHeaders;
|
||||
/** Query string params to be embedded in the request URL. Default: `null` */
|
||||
query?: Record<string, any>;
|
||||
/** Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline have completed. Default: `true` if `method` is `HEAD` or `GET`. */
|
||||
@ -127,7 +129,7 @@ declare namespace Dispatcher {
|
||||
origin: string | URL;
|
||||
path: string;
|
||||
/** Default: `null` */
|
||||
headers?: IncomingHttpHeaders | string[] | null;
|
||||
headers?: UndiciHeaders;
|
||||
/** Default: `null` */
|
||||
signal?: AbortSignal | EventEmitter | null;
|
||||
/** This argument parameter is passed through to `ConnectData` */
|
||||
@ -164,7 +166,7 @@ declare namespace Dispatcher {
|
||||
/** Default: `'GET'` */
|
||||
method?: string;
|
||||
/** Default: `null` */
|
||||
headers?: IncomingHttpHeaders | string[] | null;
|
||||
headers?: UndiciHeaders;
|
||||
/** A string of comma separated protocols, in descending preference order. Default: `'Websocket'` */
|
||||
protocol?: string;
|
||||
/** Default: `null` */
|
||||
|
75
deps/undici/src/types/h2c-client.d.ts
vendored
Normal file
75
deps/undici/src/types/h2c-client.d.ts
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
import { URL } from 'url'
|
||||
import Dispatcher from './dispatcher'
|
||||
import buildConnector from './connector'
|
||||
|
||||
type H2ClientOptions = Omit<Dispatcher.ConnectOptions, 'origin'>
|
||||
|
||||
/**
|
||||
* A basic H2C client, mapped on top a single TCP connection. Pipelining is disabled by default.
|
||||
*/
|
||||
export class H2CClient extends Dispatcher {
|
||||
constructor (url: string | URL, options?: H2CClient.Options)
|
||||
/** Property to get and set the pipelining factor. */
|
||||
pipelining: number
|
||||
/** `true` after `client.close()` has been called. */
|
||||
closed: boolean
|
||||
/** `true` after `client.destroyed()` has been called or `client.close()` has been called and the client shutdown has completed. */
|
||||
destroyed: boolean
|
||||
|
||||
// Override dispatcher APIs.
|
||||
override connect (
|
||||
options: H2ClientOptions
|
||||
): Promise<Dispatcher.ConnectData>
|
||||
override connect (
|
||||
options: H2ClientOptions,
|
||||
callback: (err: Error | null, data: Dispatcher.ConnectData) => void
|
||||
): void
|
||||
}
|
||||
|
||||
export declare namespace H2CClient {
|
||||
export interface Options {
|
||||
/** The maximum length of request headers in bytes. Default: Node.js' `--max-http-header-size` or `16384` (16KiB). */
|
||||
maxHeaderSize?: number;
|
||||
/** The amount of time, in milliseconds, the parser will wait to receive the complete HTTP headers (Node 14 and above only). Default: `300e3` milliseconds (300s). */
|
||||
headersTimeout?: number;
|
||||
/** TODO */
|
||||
connectTimeout?: number;
|
||||
/** The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use `0` to disable it entirely. Default: `300e3` milliseconds (300s). */
|
||||
bodyTimeout?: number;
|
||||
/** the timeout, in milliseconds, after which a socket without active requests will time out. Monitors time between activity on a connected socket. This value may be overridden by *keep-alive* hints from the server. Default: `4e3` milliseconds (4s). */
|
||||
keepAliveTimeout?: number;
|
||||
/** the maximum allowed `idleTimeout`, in milliseconds, when overridden by *keep-alive* hints from the server. Default: `600e3` milliseconds (10min). */
|
||||
keepAliveMaxTimeout?: number;
|
||||
/** A number of milliseconds subtracted from server *keep-alive* hints when overriding `idleTimeout` to account for timing inaccuracies caused by e.g. transport latency. Default: `1e3` milliseconds (1s). */
|
||||
keepAliveTimeoutThreshold?: number;
|
||||
/** TODO */
|
||||
socketPath?: string;
|
||||
/** The amount of concurrent requests to be sent over the single TCP/TLS connection according to [RFC7230](https://tools.ietf.org/html/rfc7230#section-6.3.2). Default: `1`. */
|
||||
pipelining?: number;
|
||||
/** If `true`, an error is thrown when the request content-length header doesn't match the length of the request body. Default: `true`. */
|
||||
strictContentLength?: boolean;
|
||||
/** TODO */
|
||||
maxCachedSessions?: number;
|
||||
/** TODO */
|
||||
maxRedirections?: number;
|
||||
/** TODO */
|
||||
connect?: Omit<Partial<buildConnector.BuildOptions>, 'allowH2'> | buildConnector.connector;
|
||||
/** TODO */
|
||||
maxRequestsPerClient?: number;
|
||||
/** TODO */
|
||||
localAddress?: string;
|
||||
/** Max response body size in bytes, -1 is disabled */
|
||||
maxResponseSize?: number;
|
||||
/** Enables a family autodetection algorithm that loosely implements section 5 of RFC 8305. */
|
||||
autoSelectFamily?: boolean;
|
||||
/** The amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. */
|
||||
autoSelectFamilyAttemptTimeout?: number;
|
||||
/**
|
||||
* @description Dictates the maximum number of concurrent streams for a single H2 session. It can be overridden by a SETTINGS remote frame.
|
||||
* @default 100
|
||||
*/
|
||||
maxConcurrentStreams?: number
|
||||
}
|
||||
}
|
||||
|
||||
export default H2CClient
|
4
deps/undici/src/types/index.d.ts
vendored
4
deps/undici/src/types/index.d.ts
vendored
@ -6,6 +6,7 @@ import { RedirectHandler, DecoratorHandler } from './handlers'
|
||||
|
||||
import BalancedPool from './balanced-pool'
|
||||
import Client from './client'
|
||||
import H2CClient from './h2c-client'
|
||||
import buildConnector from './connector'
|
||||
import errors from './errors'
|
||||
import Agent from './agent'
|
||||
@ -32,7 +33,7 @@ export * from './content-type'
|
||||
export * from './cache'
|
||||
export { Interceptable } from './mock-interceptor'
|
||||
|
||||
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, interceptors, MockClient, MockPool, MockAgent, MockCallHistory, MockCallHistoryLog, mockErrors, ProxyAgent, EnvHttpProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent }
|
||||
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, interceptors, MockClient, MockPool, MockAgent, MockCallHistory, MockCallHistoryLog, mockErrors, ProxyAgent, EnvHttpProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent, H2CClient }
|
||||
export default Undici
|
||||
|
||||
declare namespace Undici {
|
||||
@ -43,6 +44,7 @@ declare namespace Undici {
|
||||
const RetryHandler: typeof import ('./retry-handler').default
|
||||
const BalancedPool: typeof import('./balanced-pool').default
|
||||
const Client: typeof import('./client').default
|
||||
const H2CClient: typeof import('./h2c-client').default
|
||||
const buildConnector: typeof import('./connector').default
|
||||
const errors: typeof import('./errors').default
|
||||
const Agent: typeof import('./agent').default
|
||||
|
1
deps/undici/src/types/websocket.d.ts
vendored
1
deps/undici/src/types/websocket.d.ts
vendored
@ -1,6 +1,7 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
import type { Blob } from 'buffer'
|
||||
import type { ReadableStream, WritableStream } from 'stream/web'
|
||||
import type { MessagePort } from 'worker_threads'
|
||||
import {
|
||||
EventInit,
|
||||
|
581
deps/undici/undici.js
vendored
581
deps/undici/undici.js
vendored
@ -499,6 +499,242 @@ var require_dispatcher = __commonJS({
|
||||
}
|
||||
});
|
||||
|
||||
// lib/util/timers.js
|
||||
var require_timers = __commonJS({
|
||||
"lib/util/timers.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var fastNow = 0;
|
||||
var RESOLUTION_MS = 1e3;
|
||||
var TICK_MS = (RESOLUTION_MS >> 1) - 1;
|
||||
var fastNowTimeout;
|
||||
var kFastTimer = Symbol("kFastTimer");
|
||||
var fastTimers = [];
|
||||
var NOT_IN_LIST = -2;
|
||||
var TO_BE_CLEARED = -1;
|
||||
var PENDING = 0;
|
||||
var ACTIVE = 1;
|
||||
function onTick() {
|
||||
fastNow += TICK_MS;
|
||||
let idx = 0;
|
||||
let len = fastTimers.length;
|
||||
while (idx < len) {
|
||||
const timer = fastTimers[idx];
|
||||
if (timer._state === PENDING) {
|
||||
timer._idleStart = fastNow - TICK_MS;
|
||||
timer._state = ACTIVE;
|
||||
} else if (timer._state === ACTIVE && fastNow >= timer._idleStart + timer._idleTimeout) {
|
||||
timer._state = TO_BE_CLEARED;
|
||||
timer._idleStart = -1;
|
||||
timer._onTimeout(timer._timerArg);
|
||||
}
|
||||
if (timer._state === TO_BE_CLEARED) {
|
||||
timer._state = NOT_IN_LIST;
|
||||
if (--len !== 0) {
|
||||
fastTimers[idx] = fastTimers[len];
|
||||
}
|
||||
} else {
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
fastTimers.length = len;
|
||||
if (fastTimers.length !== 0) {
|
||||
refreshTimeout();
|
||||
}
|
||||
}
|
||||
__name(onTick, "onTick");
|
||||
function refreshTimeout() {
|
||||
if (fastNowTimeout) {
|
||||
fastNowTimeout.refresh();
|
||||
} else {
|
||||
clearTimeout(fastNowTimeout);
|
||||
fastNowTimeout = setTimeout(onTick, TICK_MS);
|
||||
if (fastNowTimeout.unref) {
|
||||
fastNowTimeout.unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
__name(refreshTimeout, "refreshTimeout");
|
||||
var FastTimer = class {
|
||||
static {
|
||||
__name(this, "FastTimer");
|
||||
}
|
||||
[kFastTimer] = true;
|
||||
/**
|
||||
* The state of the timer, which can be one of the following:
|
||||
* - NOT_IN_LIST (-2)
|
||||
* - TO_BE_CLEARED (-1)
|
||||
* - PENDING (0)
|
||||
* - ACTIVE (1)
|
||||
*
|
||||
* @type {-2|-1|0|1}
|
||||
* @private
|
||||
*/
|
||||
_state = NOT_IN_LIST;
|
||||
/**
|
||||
* The number of milliseconds to wait before calling the callback.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
_idleTimeout = -1;
|
||||
/**
|
||||
* The time in milliseconds when the timer was started. This value is used to
|
||||
* calculate when the timer should expire.
|
||||
*
|
||||
* @type {number}
|
||||
* @default -1
|
||||
* @private
|
||||
*/
|
||||
_idleStart = -1;
|
||||
/**
|
||||
* The function to be executed when the timer expires.
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
_onTimeout;
|
||||
/**
|
||||
* The argument to be passed to the callback when the timer expires.
|
||||
*
|
||||
* @type {*}
|
||||
* @private
|
||||
*/
|
||||
_timerArg;
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Function} callback A function to be executed after the timer
|
||||
* expires.
|
||||
* @param {number} delay The time, in milliseconds that the timer should wait
|
||||
* before the specified function or code is executed.
|
||||
* @param {*} arg
|
||||
*/
|
||||
constructor(callback, delay, arg) {
|
||||
this._onTimeout = callback;
|
||||
this._idleTimeout = delay;
|
||||
this._timerArg = arg;
|
||||
this.refresh();
|
||||
}
|
||||
/**
|
||||
* Sets the timer's start time to the current time, and reschedules the timer
|
||||
* to call its callback at the previously specified duration adjusted to the
|
||||
* current time.
|
||||
* Using this on a timer that has already called its callback will reactivate
|
||||
* the timer.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
refresh() {
|
||||
if (this._state === NOT_IN_LIST) {
|
||||
fastTimers.push(this);
|
||||
}
|
||||
if (!fastNowTimeout || fastTimers.length === 1) {
|
||||
refreshTimeout();
|
||||
}
|
||||
this._state = PENDING;
|
||||
}
|
||||
/**
|
||||
* The `clear` method cancels the timer, preventing it from executing.
|
||||
*
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
clear() {
|
||||
this._state = TO_BE_CLEARED;
|
||||
this._idleStart = -1;
|
||||
}
|
||||
};
|
||||
module2.exports = {
|
||||
/**
|
||||
* The setTimeout() method sets a timer which executes a function once the
|
||||
* timer expires.
|
||||
* @param {Function} callback A function to be executed after the timer
|
||||
* expires.
|
||||
* @param {number} delay The time, in milliseconds that the timer should
|
||||
* wait before the specified function or code is executed.
|
||||
* @param {*} [arg] An optional argument to be passed to the callback function
|
||||
* when the timer expires.
|
||||
* @returns {NodeJS.Timeout|FastTimer}
|
||||
*/
|
||||
setTimeout(callback, delay, arg) {
|
||||
return delay <= RESOLUTION_MS ? setTimeout(callback, delay, arg) : new FastTimer(callback, delay, arg);
|
||||
},
|
||||
/**
|
||||
* The clearTimeout method cancels an instantiated Timer previously created
|
||||
* by calling setTimeout.
|
||||
*
|
||||
* @param {NodeJS.Timeout|FastTimer} timeout
|
||||
*/
|
||||
clearTimeout(timeout) {
|
||||
if (timeout[kFastTimer]) {
|
||||
timeout.clear();
|
||||
} else {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* The setFastTimeout() method sets a fastTimer which executes a function once
|
||||
* the timer expires.
|
||||
* @param {Function} callback A function to be executed after the timer
|
||||
* expires.
|
||||
* @param {number} delay The time, in milliseconds that the timer should
|
||||
* wait before the specified function or code is executed.
|
||||
* @param {*} [arg] An optional argument to be passed to the callback function
|
||||
* when the timer expires.
|
||||
* @returns {FastTimer}
|
||||
*/
|
||||
setFastTimeout(callback, delay, arg) {
|
||||
return new FastTimer(callback, delay, arg);
|
||||
},
|
||||
/**
|
||||
* The clearTimeout method cancels an instantiated FastTimer previously
|
||||
* created by calling setFastTimeout.
|
||||
*
|
||||
* @param {FastTimer} timeout
|
||||
*/
|
||||
clearFastTimeout(timeout) {
|
||||
timeout.clear();
|
||||
},
|
||||
/**
|
||||
* The now method returns the value of the internal fast timer clock.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
now() {
|
||||
return fastNow;
|
||||
},
|
||||
/**
|
||||
* Trigger the onTick function to process the fastTimers array.
|
||||
* Exported for testing purposes only.
|
||||
* Marking as deprecated to discourage any use outside of testing.
|
||||
* @deprecated
|
||||
* @param {number} [delay=0] The delay in milliseconds to add to the now value.
|
||||
*/
|
||||
tick(delay = 0) {
|
||||
fastNow += delay - RESOLUTION_MS + 1;
|
||||
onTick();
|
||||
onTick();
|
||||
},
|
||||
/**
|
||||
* Reset FastTimers.
|
||||
* Exported for testing purposes only.
|
||||
* Marking as deprecated to discourage any use outside of testing.
|
||||
* @deprecated
|
||||
*/
|
||||
reset() {
|
||||
fastNow = 0;
|
||||
fastTimers.length = 0;
|
||||
clearTimeout(fastNowTimeout);
|
||||
fastNowTimeout = null;
|
||||
},
|
||||
/**
|
||||
* Exporting for testing purposes only.
|
||||
* Marking as deprecated to discourage any use outside of testing.
|
||||
* @deprecated
|
||||
*/
|
||||
kFastTimer
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// lib/core/constants.js
|
||||
var require_constants = __commonJS({
|
||||
"lib/core/constants.js"(exports2, module2) {
|
||||
@ -789,7 +1025,8 @@ var require_util = __commonJS({
|
||||
var nodeUtil = require("node:util");
|
||||
var { stringify } = require("node:querystring");
|
||||
var { EventEmitter: EE } = require("node:events");
|
||||
var { InvalidArgumentError } = require_errors();
|
||||
var timers = require_timers();
|
||||
var { InvalidArgumentError, ConnectTimeoutError } = require_errors();
|
||||
var { headerNameLowerCasedRecord } = require_constants();
|
||||
var { tree } = require_tree();
|
||||
var [nodeMajor, nodeMinor] = process.versions.node.split(".", 2).map((v) => Number(v));
|
||||
@ -807,6 +1044,9 @@ var require_util = __commonJS({
|
||||
yield* this[kBody];
|
||||
}
|
||||
};
|
||||
function noop() {
|
||||
}
|
||||
__name(noop, "noop");
|
||||
function wrapRequestBody(body) {
|
||||
if (isStream(body)) {
|
||||
if (bodyLength(body) === 0) {
|
||||
@ -1264,6 +1504,51 @@ var require_util = __commonJS({
|
||||
}
|
||||
}
|
||||
__name(errorRequest, "errorRequest");
|
||||
var setupConnectTimeout = process.platform === "win32" ? (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop;
|
||||
}
|
||||
let s1 = null;
|
||||
let s2 = null;
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
s1 = setImmediate(() => {
|
||||
s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts));
|
||||
});
|
||||
}, opts.timeout);
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer);
|
||||
clearImmediate(s1);
|
||||
clearImmediate(s2);
|
||||
};
|
||||
} : (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop;
|
||||
}
|
||||
let s1 = null;
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
s1 = setImmediate(() => {
|
||||
onConnectTimeout(socketWeakRef.deref(), opts);
|
||||
});
|
||||
}, opts.timeout);
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer);
|
||||
clearImmediate(s1);
|
||||
};
|
||||
};
|
||||
function onConnectTimeout(socket, opts) {
|
||||
if (socket == null) {
|
||||
return;
|
||||
}
|
||||
let message = "Connect Timeout Error";
|
||||
if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
|
||||
message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(", ")},`;
|
||||
} else {
|
||||
message += ` (attempted address: ${opts.hostname}:${opts.port},`;
|
||||
}
|
||||
message += ` timeout: ${opts.timeout}ms)`;
|
||||
destroy(socket, new ConnectTimeoutError(message));
|
||||
}
|
||||
__name(onConnectTimeout, "onConnectTimeout");
|
||||
var kEnumerableProperty = /* @__PURE__ */ Object.create(null);
|
||||
kEnumerableProperty.enumerable = true;
|
||||
var normalizedMethodRecordsBase = {
|
||||
@ -1330,7 +1615,8 @@ var require_util = __commonJS({
|
||||
nodeMajor,
|
||||
nodeMinor,
|
||||
safeHTTPMethods: Object.freeze(["GET", "HEAD", "OPTIONS", "TRACE"]),
|
||||
wrapRequestBody
|
||||
wrapRequestBody,
|
||||
setupConnectTimeout
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -2374,242 +2660,6 @@ var require_request = __commonJS({
|
||||
}
|
||||
});
|
||||
|
||||
// lib/util/timers.js
|
||||
var require_timers = __commonJS({
|
||||
"lib/util/timers.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var fastNow = 0;
|
||||
var RESOLUTION_MS = 1e3;
|
||||
var TICK_MS = (RESOLUTION_MS >> 1) - 1;
|
||||
var fastNowTimeout;
|
||||
var kFastTimer = Symbol("kFastTimer");
|
||||
var fastTimers = [];
|
||||
var NOT_IN_LIST = -2;
|
||||
var TO_BE_CLEARED = -1;
|
||||
var PENDING = 0;
|
||||
var ACTIVE = 1;
|
||||
function onTick() {
|
||||
fastNow += TICK_MS;
|
||||
let idx = 0;
|
||||
let len = fastTimers.length;
|
||||
while (idx < len) {
|
||||
const timer = fastTimers[idx];
|
||||
if (timer._state === PENDING) {
|
||||
timer._idleStart = fastNow - TICK_MS;
|
||||
timer._state = ACTIVE;
|
||||
} else if (timer._state === ACTIVE && fastNow >= timer._idleStart + timer._idleTimeout) {
|
||||
timer._state = TO_BE_CLEARED;
|
||||
timer._idleStart = -1;
|
||||
timer._onTimeout(timer._timerArg);
|
||||
}
|
||||
if (timer._state === TO_BE_CLEARED) {
|
||||
timer._state = NOT_IN_LIST;
|
||||
if (--len !== 0) {
|
||||
fastTimers[idx] = fastTimers[len];
|
||||
}
|
||||
} else {
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
fastTimers.length = len;
|
||||
if (fastTimers.length !== 0) {
|
||||
refreshTimeout();
|
||||
}
|
||||
}
|
||||
__name(onTick, "onTick");
|
||||
function refreshTimeout() {
|
||||
if (fastNowTimeout) {
|
||||
fastNowTimeout.refresh();
|
||||
} else {
|
||||
clearTimeout(fastNowTimeout);
|
||||
fastNowTimeout = setTimeout(onTick, TICK_MS);
|
||||
if (fastNowTimeout.unref) {
|
||||
fastNowTimeout.unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
__name(refreshTimeout, "refreshTimeout");
|
||||
var FastTimer = class {
|
||||
static {
|
||||
__name(this, "FastTimer");
|
||||
}
|
||||
[kFastTimer] = true;
|
||||
/**
|
||||
* The state of the timer, which can be one of the following:
|
||||
* - NOT_IN_LIST (-2)
|
||||
* - TO_BE_CLEARED (-1)
|
||||
* - PENDING (0)
|
||||
* - ACTIVE (1)
|
||||
*
|
||||
* @type {-2|-1|0|1}
|
||||
* @private
|
||||
*/
|
||||
_state = NOT_IN_LIST;
|
||||
/**
|
||||
* The number of milliseconds to wait before calling the callback.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
_idleTimeout = -1;
|
||||
/**
|
||||
* The time in milliseconds when the timer was started. This value is used to
|
||||
* calculate when the timer should expire.
|
||||
*
|
||||
* @type {number}
|
||||
* @default -1
|
||||
* @private
|
||||
*/
|
||||
_idleStart = -1;
|
||||
/**
|
||||
* The function to be executed when the timer expires.
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
_onTimeout;
|
||||
/**
|
||||
* The argument to be passed to the callback when the timer expires.
|
||||
*
|
||||
* @type {*}
|
||||
* @private
|
||||
*/
|
||||
_timerArg;
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Function} callback A function to be executed after the timer
|
||||
* expires.
|
||||
* @param {number} delay The time, in milliseconds that the timer should wait
|
||||
* before the specified function or code is executed.
|
||||
* @param {*} arg
|
||||
*/
|
||||
constructor(callback, delay, arg) {
|
||||
this._onTimeout = callback;
|
||||
this._idleTimeout = delay;
|
||||
this._timerArg = arg;
|
||||
this.refresh();
|
||||
}
|
||||
/**
|
||||
* Sets the timer's start time to the current time, and reschedules the timer
|
||||
* to call its callback at the previously specified duration adjusted to the
|
||||
* current time.
|
||||
* Using this on a timer that has already called its callback will reactivate
|
||||
* the timer.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
refresh() {
|
||||
if (this._state === NOT_IN_LIST) {
|
||||
fastTimers.push(this);
|
||||
}
|
||||
if (!fastNowTimeout || fastTimers.length === 1) {
|
||||
refreshTimeout();
|
||||
}
|
||||
this._state = PENDING;
|
||||
}
|
||||
/**
|
||||
* The `clear` method cancels the timer, preventing it from executing.
|
||||
*
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
clear() {
|
||||
this._state = TO_BE_CLEARED;
|
||||
this._idleStart = -1;
|
||||
}
|
||||
};
|
||||
module2.exports = {
|
||||
/**
|
||||
* The setTimeout() method sets a timer which executes a function once the
|
||||
* timer expires.
|
||||
* @param {Function} callback A function to be executed after the timer
|
||||
* expires.
|
||||
* @param {number} delay The time, in milliseconds that the timer should
|
||||
* wait before the specified function or code is executed.
|
||||
* @param {*} [arg] An optional argument to be passed to the callback function
|
||||
* when the timer expires.
|
||||
* @returns {NodeJS.Timeout|FastTimer}
|
||||
*/
|
||||
setTimeout(callback, delay, arg) {
|
||||
return delay <= RESOLUTION_MS ? setTimeout(callback, delay, arg) : new FastTimer(callback, delay, arg);
|
||||
},
|
||||
/**
|
||||
* The clearTimeout method cancels an instantiated Timer previously created
|
||||
* by calling setTimeout.
|
||||
*
|
||||
* @param {NodeJS.Timeout|FastTimer} timeout
|
||||
*/
|
||||
clearTimeout(timeout) {
|
||||
if (timeout[kFastTimer]) {
|
||||
timeout.clear();
|
||||
} else {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* The setFastTimeout() method sets a fastTimer which executes a function once
|
||||
* the timer expires.
|
||||
* @param {Function} callback A function to be executed after the timer
|
||||
* expires.
|
||||
* @param {number} delay The time, in milliseconds that the timer should
|
||||
* wait before the specified function or code is executed.
|
||||
* @param {*} [arg] An optional argument to be passed to the callback function
|
||||
* when the timer expires.
|
||||
* @returns {FastTimer}
|
||||
*/
|
||||
setFastTimeout(callback, delay, arg) {
|
||||
return new FastTimer(callback, delay, arg);
|
||||
},
|
||||
/**
|
||||
* The clearTimeout method cancels an instantiated FastTimer previously
|
||||
* created by calling setFastTimeout.
|
||||
*
|
||||
* @param {FastTimer} timeout
|
||||
*/
|
||||
clearFastTimeout(timeout) {
|
||||
timeout.clear();
|
||||
},
|
||||
/**
|
||||
* The now method returns the value of the internal fast timer clock.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
now() {
|
||||
return fastNow;
|
||||
},
|
||||
/**
|
||||
* Trigger the onTick function to process the fastTimers array.
|
||||
* Exported for testing purposes only.
|
||||
* Marking as deprecated to discourage any use outside of testing.
|
||||
* @deprecated
|
||||
* @param {number} [delay=0] The delay in milliseconds to add to the now value.
|
||||
*/
|
||||
tick(delay = 0) {
|
||||
fastNow += delay - RESOLUTION_MS + 1;
|
||||
onTick();
|
||||
onTick();
|
||||
},
|
||||
/**
|
||||
* Reset FastTimers.
|
||||
* Exported for testing purposes only.
|
||||
* Marking as deprecated to discourage any use outside of testing.
|
||||
* @deprecated
|
||||
*/
|
||||
reset() {
|
||||
fastNow = 0;
|
||||
fastTimers.length = 0;
|
||||
clearTimeout(fastNowTimeout);
|
||||
fastNowTimeout = null;
|
||||
},
|
||||
/**
|
||||
* Exporting for testing purposes only.
|
||||
* Marking as deprecated to discourage any use outside of testing.
|
||||
* @deprecated
|
||||
*/
|
||||
kFastTimer
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// lib/core/connect.js
|
||||
var require_connect = __commonJS({
|
||||
"lib/core/connect.js"(exports2, module2) {
|
||||
@ -2617,11 +2667,7 @@ var require_connect = __commonJS({
|
||||
var net = require("node:net");
|
||||
var assert = require("node:assert");
|
||||
var util = require_util();
|
||||
var { InvalidArgumentError, ConnectTimeoutError } = require_errors();
|
||||
var timers = require_timers();
|
||||
function noop() {
|
||||
}
|
||||
__name(noop, "noop");
|
||||
var { InvalidArgumentError } = require_errors();
|
||||
var tls;
|
||||
var SessionCache;
|
||||
if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) {
|
||||
@ -2704,7 +2750,6 @@ var require_connect = __commonJS({
|
||||
servername,
|
||||
session,
|
||||
localAddress,
|
||||
// TODO(HTTP/2): Add support for h2c
|
||||
ALPNProtocols: allowH2 ? ["http/1.1", "h2"] : ["http/1.1"],
|
||||
socket: httpSocket,
|
||||
// upgrade socket connection
|
||||
@ -2730,7 +2775,7 @@ var require_connect = __commonJS({
|
||||
const keepAliveInitialDelay = options.keepAliveInitialDelay === void 0 ? 6e4 : options.keepAliveInitialDelay;
|
||||
socket.setKeepAlive(true, keepAliveInitialDelay);
|
||||
}
|
||||
const clearConnectTimeout = setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port });
|
||||
const clearConnectTimeout = util.setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port });
|
||||
socket.setNoDelay(true).once(protocol === "https:" ? "secureConnect" : "connect", function() {
|
||||
queueMicrotask(clearConnectTimeout);
|
||||
if (callback) {
|
||||
@ -2750,51 +2795,6 @@ var require_connect = __commonJS({
|
||||
}, "connect");
|
||||
}
|
||||
__name(buildConnector, "buildConnector");
|
||||
var setupConnectTimeout = process.platform === "win32" ? (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop;
|
||||
}
|
||||
let s1 = null;
|
||||
let s2 = null;
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
s1 = setImmediate(() => {
|
||||
s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts));
|
||||
});
|
||||
}, opts.timeout);
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer);
|
||||
clearImmediate(s1);
|
||||
clearImmediate(s2);
|
||||
};
|
||||
} : (socketWeakRef, opts) => {
|
||||
if (!opts.timeout) {
|
||||
return noop;
|
||||
}
|
||||
let s1 = null;
|
||||
const fastTimer = timers.setFastTimeout(() => {
|
||||
s1 = setImmediate(() => {
|
||||
onConnectTimeout(socketWeakRef.deref(), opts);
|
||||
});
|
||||
}, opts.timeout);
|
||||
return () => {
|
||||
timers.clearFastTimeout(fastTimer);
|
||||
clearImmediate(s1);
|
||||
};
|
||||
};
|
||||
function onConnectTimeout(socket, opts) {
|
||||
if (socket == null) {
|
||||
return;
|
||||
}
|
||||
let message = "Connect Timeout Error";
|
||||
if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
|
||||
message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(", ")},`;
|
||||
} else {
|
||||
message += ` (attempted address: ${opts.hostname}:${opts.port},`;
|
||||
}
|
||||
message += ` timeout: ${opts.timeout}ms)`;
|
||||
util.destroy(socket, new ConnectTimeoutError(message));
|
||||
}
|
||||
__name(onConnectTimeout, "onConnectTimeout");
|
||||
module2.exports = buildConnector;
|
||||
}
|
||||
});
|
||||
@ -7619,6 +7619,7 @@ var require_client_h2 = __commonJS({
|
||||
}
|
||||
assert(client[kRunning] === 0);
|
||||
client.emit("disconnect", client[kUrl], [client], err);
|
||||
client.emit("connectionError", client[kUrl], [client], err);
|
||||
client[kResume]();
|
||||
}
|
||||
__name(onHttp2SessionGoAway, "onHttp2SessionGoAway");
|
||||
|
@ -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.6.0"
|
||||
#define UNDICI_VERSION "7.8.0"
|
||||
#endif // SRC_UNDICI_VERSION_H_
|
||||
|
Loading…
Reference in New Issue
Block a user