mirror of
https://github.com/nodejs/node.git
synced 2025-05-20 22:43:26 +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`
|
* **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.
|
* **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`
|
* **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.
|
* **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.
|
* **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.
|
* **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`)
|
Returns: `PendingInterceptor[]` (where `PendingInterceptor` is a `MockDispatch` with an additional `origin: string`)
|
||||||
|
|
||||||
#### Example - List all pending inteceptors
|
#### Example - List all pending interceptors
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const agent = new MockAgent()
|
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 ProxyAgent = require('./lib/dispatcher/proxy-agent')
|
||||||
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
|
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
|
||||||
const RetryAgent = require('./lib/dispatcher/retry-agent')
|
const RetryAgent = require('./lib/dispatcher/retry-agent')
|
||||||
|
const H2CClient = require('./lib/dispatcher/h2c-client')
|
||||||
const errors = require('./lib/core/errors')
|
const errors = require('./lib/core/errors')
|
||||||
const util = require('./lib/core/util')
|
const util = require('./lib/core/util')
|
||||||
const { InvalidArgumentError } = errors
|
const { InvalidArgumentError } = errors
|
||||||
@ -33,6 +34,7 @@ module.exports.Agent = Agent
|
|||||||
module.exports.ProxyAgent = ProxyAgent
|
module.exports.ProxyAgent = ProxyAgent
|
||||||
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
|
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
|
||||||
module.exports.RetryAgent = RetryAgent
|
module.exports.RetryAgent = RetryAgent
|
||||||
|
module.exports.H2CClient = H2CClient
|
||||||
module.exports.RetryHandler = RetryHandler
|
module.exports.RetryHandler = RetryHandler
|
||||||
|
|
||||||
module.exports.DecoratorHandler = DecoratorHandler
|
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 = new DatabaseSync(opts?.location ?? ':memory:')
|
||||||
|
|
||||||
this.#db.exec(`
|
this.#db.exec(`
|
||||||
|
PRAGMA journal_mode = WAL;
|
||||||
|
PRAGMA synchronous = NORMAL;
|
||||||
|
PRAGMA temp_store = memory;
|
||||||
|
PRAGMA optimize;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION} (
|
CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION} (
|
||||||
-- Data specific to us
|
-- Data specific to us
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@ -134,9 +139,8 @@ module.exports = class SqliteCacheStore {
|
|||||||
staleAt INTEGER NOT NULL
|
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}_getValuesQuery ON cacheInterceptorV${VERSION}(url, method, deleteAt);
|
||||||
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_method ON cacheInterceptorV${VERSION}(method);
|
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteByUrlQuery ON cacheInterceptorV${VERSION}(deleteAt);
|
||||||
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteAt ON cacheInterceptorV${VERSION}(deleteAt);
|
|
||||||
`)
|
`)
|
||||||
|
|
||||||
this.#getValuesQuery = this.#db.prepare(`
|
this.#getValuesQuery = this.#db.prepare(`
|
||||||
@ -346,7 +350,7 @@ module.exports = class SqliteCacheStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#prune () {
|
#prune () {
|
||||||
if (this.size <= this.#maxCount) {
|
if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) {
|
||||||
return 0
|
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 net = require('node:net')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const util = require('./util')
|
const util = require('./util')
|
||||||
const { InvalidArgumentError, ConnectTimeoutError } = require('./errors')
|
const { InvalidArgumentError } = require('./errors')
|
||||||
const timers = require('../util/timers')
|
|
||||||
|
|
||||||
function noop () {}
|
|
||||||
|
|
||||||
let tls // include tls conditionally since it is not always available
|
let tls // include tls conditionally since it is not always available
|
||||||
|
|
||||||
@ -106,7 +103,6 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
|
|||||||
servername,
|
servername,
|
||||||
session,
|
session,
|
||||||
localAddress,
|
localAddress,
|
||||||
// TODO(HTTP/2): Add support for h2c
|
|
||||||
ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'],
|
ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'],
|
||||||
socket: httpSocket, // upgrade socket connection
|
socket: httpSocket, // upgrade socket connection
|
||||||
port,
|
port,
|
||||||
@ -138,7 +134,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
|
|||||||
socket.setKeepAlive(true, 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
|
socket
|
||||||
.setNoDelay(true)
|
.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
|
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 nodeUtil = require('node:util')
|
||||||
const { stringify } = require('node:querystring')
|
const { stringify } = require('node:querystring')
|
||||||
const { EventEmitter: EE } = require('node:events')
|
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 { headerNameLowerCasedRecord } = require('./constants')
|
||||||
const { tree } = require('./tree')
|
const { tree } = require('./tree')
|
||||||
|
|
||||||
@ -28,6 +29,8 @@ class BodyAsyncIterable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function noop () {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {*} body
|
* @param {*} body
|
||||||
* @returns {*}
|
* @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)
|
const kEnumerableProperty = Object.create(null)
|
||||||
kEnumerableProperty.enumerable = true
|
kEnumerableProperty.enumerable = true
|
||||||
|
|
||||||
@ -908,5 +983,6 @@ module.exports = {
|
|||||||
nodeMajor,
|
nodeMajor,
|
||||||
nodeMinor,
|
nodeMinor,
|
||||||
safeHTTPMethods: Object.freeze(['GET', 'HEAD', 'OPTIONS', 'TRACE']),
|
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)
|
assert(client[kRunning] === 0)
|
||||||
|
|
||||||
client.emit('disconnect', client[kUrl], [client], err)
|
client.emit('disconnect', client[kUrl], [client], err)
|
||||||
|
client.emit('connectionError', client[kUrl], [client], err)
|
||||||
|
|
||||||
client[kResume]()
|
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
|
> 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
|
> 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",
|
"name": "undici",
|
||||||
"version": "7.6.0",
|
"version": "7.8.0",
|
||||||
"description": "An HTTP/1.1 client, written from scratch for Node.js",
|
"description": "An HTTP/1.1 client, written from scratch for Node.js",
|
||||||
"homepage": "https://undici.nodejs.org",
|
"homepage": "https://undici.nodejs.org",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
@ -80,7 +80,7 @@
|
|||||||
"test:fuzzing": "node test/fuzzing/fuzzing.test.js",
|
"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: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": "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:h2:fetch": "npm run build:node && borp -p \"test/fetch/http2*.js\"",
|
||||||
"test:interceptors": "borp -p \"test/interceptors/*.js\"",
|
"test:interceptors": "borp -p \"test/interceptors/*.js\"",
|
||||||
"test:jest": "cross-env NODE_V8_COVERAGE= jest",
|
"test:jest": "cross-env NODE_V8_COVERAGE= jest",
|
||||||
@ -116,7 +116,7 @@
|
|||||||
"c8": "^10.0.0",
|
"c8": "^10.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dns-packet": "^5.4.0",
|
"dns-packet": "^5.4.0",
|
||||||
"esbuild": "^0.24.0",
|
"esbuild": "^0.25.2",
|
||||||
"eslint": "^9.9.0",
|
"eslint": "^9.9.0",
|
||||||
"fast-check": "^3.17.1",
|
"fast-check": "^3.17.1",
|
||||||
"https-pem": "^3.0.0",
|
"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 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. */
|
/** Dispatcher is the core API used to dispatch requests. */
|
||||||
declare class Dispatcher extends EventEmitter {
|
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. */
|
/** 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` */
|
/** Default: `null` */
|
||||||
body?: string | Buffer | Uint8Array | Readable | null | FormData;
|
body?: string | Buffer | Uint8Array | Readable | null | FormData;
|
||||||
/** Default: `null` */
|
/** 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 string params to be embedded in the request URL. Default: `null` */
|
||||||
query?: Record<string, any>;
|
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`. */
|
/** 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;
|
origin: string | URL;
|
||||||
path: string;
|
path: string;
|
||||||
/** Default: `null` */
|
/** Default: `null` */
|
||||||
headers?: IncomingHttpHeaders | string[] | null;
|
headers?: UndiciHeaders;
|
||||||
/** Default: `null` */
|
/** Default: `null` */
|
||||||
signal?: AbortSignal | EventEmitter | null;
|
signal?: AbortSignal | EventEmitter | null;
|
||||||
/** This argument parameter is passed through to `ConnectData` */
|
/** This argument parameter is passed through to `ConnectData` */
|
||||||
@ -164,7 +166,7 @@ declare namespace Dispatcher {
|
|||||||
/** Default: `'GET'` */
|
/** Default: `'GET'` */
|
||||||
method?: string;
|
method?: string;
|
||||||
/** Default: `null` */
|
/** Default: `null` */
|
||||||
headers?: IncomingHttpHeaders | string[] | null;
|
headers?: UndiciHeaders;
|
||||||
/** A string of comma separated protocols, in descending preference order. Default: `'Websocket'` */
|
/** A string of comma separated protocols, in descending preference order. Default: `'Websocket'` */
|
||||||
protocol?: string;
|
protocol?: string;
|
||||||
/** Default: `null` */
|
/** 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 BalancedPool from './balanced-pool'
|
||||||
import Client from './client'
|
import Client from './client'
|
||||||
|
import H2CClient from './h2c-client'
|
||||||
import buildConnector from './connector'
|
import buildConnector from './connector'
|
||||||
import errors from './errors'
|
import errors from './errors'
|
||||||
import Agent from './agent'
|
import Agent from './agent'
|
||||||
@ -32,7 +33,7 @@ export * from './content-type'
|
|||||||
export * from './cache'
|
export * from './cache'
|
||||||
export { Interceptable } from './mock-interceptor'
|
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
|
export default Undici
|
||||||
|
|
||||||
declare namespace Undici {
|
declare namespace Undici {
|
||||||
@ -43,6 +44,7 @@ declare namespace Undici {
|
|||||||
const RetryHandler: typeof import ('./retry-handler').default
|
const RetryHandler: typeof import ('./retry-handler').default
|
||||||
const BalancedPool: typeof import('./balanced-pool').default
|
const BalancedPool: typeof import('./balanced-pool').default
|
||||||
const Client: typeof import('./client').default
|
const Client: typeof import('./client').default
|
||||||
|
const H2CClient: typeof import('./h2c-client').default
|
||||||
const buildConnector: typeof import('./connector').default
|
const buildConnector: typeof import('./connector').default
|
||||||
const errors: typeof import('./errors').default
|
const errors: typeof import('./errors').default
|
||||||
const Agent: typeof import('./agent').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" />
|
/// <reference types="node" />
|
||||||
|
|
||||||
import type { Blob } from 'buffer'
|
import type { Blob } from 'buffer'
|
||||||
|
import type { ReadableStream, WritableStream } from 'stream/web'
|
||||||
import type { MessagePort } from 'worker_threads'
|
import type { MessagePort } from 'worker_threads'
|
||||||
import {
|
import {
|
||||||
EventInit,
|
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
|
// lib/core/constants.js
|
||||||
var require_constants = __commonJS({
|
var require_constants = __commonJS({
|
||||||
"lib/core/constants.js"(exports2, module2) {
|
"lib/core/constants.js"(exports2, module2) {
|
||||||
@ -789,7 +1025,8 @@ var require_util = __commonJS({
|
|||||||
var nodeUtil = require("node:util");
|
var nodeUtil = require("node:util");
|
||||||
var { stringify } = require("node:querystring");
|
var { stringify } = require("node:querystring");
|
||||||
var { EventEmitter: EE } = require("node:events");
|
var { EventEmitter: EE } = require("node:events");
|
||||||
var { InvalidArgumentError } = require_errors();
|
var timers = require_timers();
|
||||||
|
var { InvalidArgumentError, ConnectTimeoutError } = require_errors();
|
||||||
var { headerNameLowerCasedRecord } = require_constants();
|
var { headerNameLowerCasedRecord } = require_constants();
|
||||||
var { tree } = require_tree();
|
var { tree } = require_tree();
|
||||||
var [nodeMajor, nodeMinor] = process.versions.node.split(".", 2).map((v) => Number(v));
|
var [nodeMajor, nodeMinor] = process.versions.node.split(".", 2).map((v) => Number(v));
|
||||||
@ -807,6 +1044,9 @@ var require_util = __commonJS({
|
|||||||
yield* this[kBody];
|
yield* this[kBody];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
__name(noop, "noop");
|
||||||
function wrapRequestBody(body) {
|
function wrapRequestBody(body) {
|
||||||
if (isStream(body)) {
|
if (isStream(body)) {
|
||||||
if (bodyLength(body) === 0) {
|
if (bodyLength(body) === 0) {
|
||||||
@ -1264,6 +1504,51 @@ var require_util = __commonJS({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
__name(errorRequest, "errorRequest");
|
__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);
|
var kEnumerableProperty = /* @__PURE__ */ Object.create(null);
|
||||||
kEnumerableProperty.enumerable = true;
|
kEnumerableProperty.enumerable = true;
|
||||||
var normalizedMethodRecordsBase = {
|
var normalizedMethodRecordsBase = {
|
||||||
@ -1330,7 +1615,8 @@ var require_util = __commonJS({
|
|||||||
nodeMajor,
|
nodeMajor,
|
||||||
nodeMinor,
|
nodeMinor,
|
||||||
safeHTTPMethods: Object.freeze(["GET", "HEAD", "OPTIONS", "TRACE"]),
|
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
|
// lib/core/connect.js
|
||||||
var require_connect = __commonJS({
|
var require_connect = __commonJS({
|
||||||
"lib/core/connect.js"(exports2, module2) {
|
"lib/core/connect.js"(exports2, module2) {
|
||||||
@ -2617,11 +2667,7 @@ var require_connect = __commonJS({
|
|||||||
var net = require("node:net");
|
var net = require("node:net");
|
||||||
var assert = require("node:assert");
|
var assert = require("node:assert");
|
||||||
var util = require_util();
|
var util = require_util();
|
||||||
var { InvalidArgumentError, ConnectTimeoutError } = require_errors();
|
var { InvalidArgumentError } = require_errors();
|
||||||
var timers = require_timers();
|
|
||||||
function noop() {
|
|
||||||
}
|
|
||||||
__name(noop, "noop");
|
|
||||||
var tls;
|
var tls;
|
||||||
var SessionCache;
|
var SessionCache;
|
||||||
if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) {
|
if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) {
|
||||||
@ -2704,7 +2750,6 @@ var require_connect = __commonJS({
|
|||||||
servername,
|
servername,
|
||||||
session,
|
session,
|
||||||
localAddress,
|
localAddress,
|
||||||
// TODO(HTTP/2): Add support for h2c
|
|
||||||
ALPNProtocols: allowH2 ? ["http/1.1", "h2"] : ["http/1.1"],
|
ALPNProtocols: allowH2 ? ["http/1.1", "h2"] : ["http/1.1"],
|
||||||
socket: httpSocket,
|
socket: httpSocket,
|
||||||
// upgrade socket connection
|
// upgrade socket connection
|
||||||
@ -2730,7 +2775,7 @@ var require_connect = __commonJS({
|
|||||||
const keepAliveInitialDelay = options.keepAliveInitialDelay === void 0 ? 6e4 : options.keepAliveInitialDelay;
|
const keepAliveInitialDelay = options.keepAliveInitialDelay === void 0 ? 6e4 : options.keepAliveInitialDelay;
|
||||||
socket.setKeepAlive(true, 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() {
|
socket.setNoDelay(true).once(protocol === "https:" ? "secureConnect" : "connect", function() {
|
||||||
queueMicrotask(clearConnectTimeout);
|
queueMicrotask(clearConnectTimeout);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
@ -2750,51 +2795,6 @@ var require_connect = __commonJS({
|
|||||||
}, "connect");
|
}, "connect");
|
||||||
}
|
}
|
||||||
__name(buildConnector, "buildConnector");
|
__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;
|
module2.exports = buildConnector;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -7619,6 +7619,7 @@ var require_client_h2 = __commonJS({
|
|||||||
}
|
}
|
||||||
assert(client[kRunning] === 0);
|
assert(client[kRunning] === 0);
|
||||||
client.emit("disconnect", client[kUrl], [client], err);
|
client.emit("disconnect", client[kUrl], [client], err);
|
||||||
|
client.emit("connectionError", client[kUrl], [client], err);
|
||||||
client[kResume]();
|
client[kResume]();
|
||||||
}
|
}
|
||||||
__name(onHttp2SessionGoAway, "onHttp2SessionGoAway");
|
__name(onHttp2SessionGoAway, "onHttp2SessionGoAway");
|
||||||
|
@ -2,5 +2,5 @@
|
|||||||
// Refer to tools/dep_updaters/update-undici.sh
|
// Refer to tools/dep_updaters/update-undici.sh
|
||||||
#ifndef SRC_UNDICI_VERSION_H_
|
#ifndef SRC_UNDICI_VERSION_H_
|
||||||
#define 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_
|
#endif // SRC_UNDICI_VERSION_H_
|
||||||
|
Loading…
Reference in New Issue
Block a user