Skip to content

Commit cdedec7

Browse files
nodejs-github-botRafaelGSS
authored andcommitted
deps: update undici to 7.8.0
PR-URL: #57770 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Matthew Aitken <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Ulises Gascón <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Marco Ippolito <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
1 parent 7df9558 commit cdedec7

File tree

18 files changed

+1188
-674
lines changed

18 files changed

+1188
-674
lines changed

deps/undici/src/docs/docs/api/Dispatcher.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
194194
* **method** `string`
195195
* **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.
196196
* **body** `string | Buffer | Uint8Array | stream.Readable | Iterable | AsyncIterable | null` (optional) - Default: `null`
197-
* **headers** `UndiciHeaders | string[]` (optional) - Default: `null`.
197+
* **headers** `UndiciHeaders` (optional) - Default: `null`.
198198
* **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.
199199
* **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.
200200
* **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.
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
# Class: H2CClient
2+
3+
Extends: `undici.Dispatcher`
4+
5+
A basic H2C client.
6+
7+
**Example**
8+
9+
```js
10+
const { createServer } = require('node:http2')
11+
const { once } = require('node:events')
12+
const { H2CClient } = require('undici')
13+
14+
const server = createServer((req, res) => {
15+
res.writeHead(200)
16+
res.end('Hello, world!')
17+
})
18+
19+
server.listen()
20+
once(server, 'listening').then(() => {
21+
const client = new H2CClient(`http://localhost:${server.address().port}/`)
22+
23+
const response = await client.request({ path: '/', method: 'GET' })
24+
console.log(response.statusCode) // 200
25+
response.body.text.then((text) => {
26+
console.log(text) // Hello, world!
27+
})
28+
})
29+
```
30+
31+
## `new H2CClient(url[, options])`
32+
33+
Arguments:
34+
35+
- **url** `URL | string` - Should only include the **protocol, hostname, and port**. It only supports `http` protocol.
36+
- **options** `H2CClientOptions` (optional)
37+
38+
Returns: `H2CClient`
39+
40+
### Parameter: `H2CClientOptions`
41+
42+
- **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.
43+
- **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.
44+
- **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.
45+
- **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.
46+
- **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.
47+
- **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.
48+
- **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable.
49+
- **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.
50+
- **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.
51+
- **connect** `ConnectOptions | null` (optional) - Default: `null`.
52+
- **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.
53+
- **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.
54+
- **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.
55+
56+
#### Parameter: `H2CConnectOptions`
57+
58+
- **socketPath** `string | null` (optional) - Default: `null` - An IPC endpoint, either Unix domain socket or Windows named pipe.
59+
- **timeout** `number | null` (optional) - In milliseconds, Default `10e3`.
60+
- **servername** `string | null` (optional)
61+
- **keepAlive** `boolean | null` (optional) - Default: `true` - TCP keep-alive enabled
62+
- **keepAliveInitialDelay** `number | null` (optional) - Default: `60000` - TCP keep-alive interval for the socket in milliseconds
63+
64+
### Example - Basic Client instantiation
65+
66+
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`.
67+
68+
```js
69+
"use strict";
70+
import { H2CClient } from "undici";
71+
72+
const client = new H2CClient("http://localhost:3000");
73+
```
74+
75+
## Instance Methods
76+
77+
### `H2CClient.close([callback])`
78+
79+
Implements [`Dispatcher.close([callback])`](/docs/docs/api/Dispatcher.md#dispatcherclosecallback-promise).
80+
81+
### `H2CClient.destroy([error, callback])`
82+
83+
Implements [`Dispatcher.destroy([error, callback])`](/docs/docs/api/Dispatcher.md#dispatcherdestroyerror-callback-promise).
84+
85+
Waits until socket is closed before invoking the callback (or returning a promise if no callback is provided).
86+
87+
### `H2CClient.connect(options[, callback])`
88+
89+
See [`Dispatcher.connect(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback).
90+
91+
### `H2CClient.dispatch(options, handlers)`
92+
93+
Implements [`Dispatcher.dispatch(options, handlers)`](/docs/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler).
94+
95+
### `H2CClient.pipeline(options, handler)`
96+
97+
See [`Dispatcher.pipeline(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler).
98+
99+
### `H2CClient.request(options[, callback])`
100+
101+
See [`Dispatcher.request(options [, callback])`](/docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback).
102+
103+
### `H2CClient.stream(options, factory[, callback])`
104+
105+
See [`Dispatcher.stream(options, factory[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback).
106+
107+
### `H2CClient.upgrade(options[, callback])`
108+
109+
See [`Dispatcher.upgrade(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback).
110+
111+
## Instance Properties
112+
113+
### `H2CClient.closed`
114+
115+
- `boolean`
116+
117+
`true` after `H2CClient.close()` has been called.
118+
119+
### `H2CClient.destroyed`
120+
121+
- `boolean`
122+
123+
`true` after `client.destroyed()` has been called or `client.close()` has been called and the client shutdown has completed.
124+
125+
### `H2CClient.pipelining`
126+
127+
- `number`
128+
129+
Property to get and set the pipelining factor.
130+
131+
## Instance Events
132+
133+
### Event: `'connect'`
134+
135+
See [Dispatcher Event: `'connect'`](/docs/docs/api/Dispatcher.md#event-connect).
136+
137+
Parameters:
138+
139+
- **origin** `URL`
140+
- **targets** `Array<Dispatcher>`
141+
142+
Emitted when a socket has been created and connected. The client will connect once `client.size > 0`.
143+
144+
#### Example - Client connect event
145+
146+
```js
147+
import { createServer } from "node:http2";
148+
import { H2CClient } from "undici";
149+
import { once } from "events";
150+
151+
const server = createServer((request, response) => {
152+
response.end("Hello, World!");
153+
}).listen();
154+
155+
await once(server, "listening");
156+
157+
const client = new H2CClient(`http://localhost:${server.address().port}`);
158+
159+
client.on("connect", (origin) => {
160+
console.log(`Connected to ${origin}`); // should print before the request body statement
161+
});
162+
163+
try {
164+
const { body } = await client.request({
165+
path: "/",
166+
method: "GET",
167+
});
168+
body.setEncoding("utf-8");
169+
body.on("data", console.log);
170+
client.close();
171+
server.close();
172+
} catch (error) {
173+
console.error(error);
174+
client.close();
175+
server.close();
176+
}
177+
```
178+
179+
### Event: `'disconnect'`
180+
181+
See [Dispatcher Event: `'disconnect'`](/docs/docs/api/Dispatcher.md#event-disconnect).
182+
183+
Parameters:
184+
185+
- **origin** `URL`
186+
- **targets** `Array<Dispatcher>`
187+
- **error** `Error`
188+
189+
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`.
190+
191+
#### Example - Client disconnect event
192+
193+
```js
194+
import { createServer } from "node:http2";
195+
import { H2CClient } from "undici";
196+
import { once } from "events";
197+
198+
const server = createServer((request, response) => {
199+
response.destroy();
200+
}).listen();
201+
202+
await once(server, "listening");
203+
204+
const client = new H2CClient(`http://localhost:${server.address().port}`);
205+
206+
client.on("disconnect", (origin) => {
207+
console.log(`Disconnected from ${origin}`);
208+
});
209+
210+
try {
211+
await client.request({
212+
path: "/",
213+
method: "GET",
214+
});
215+
} catch (error) {
216+
console.error(error.message);
217+
client.close();
218+
server.close();
219+
}
220+
```
221+
222+
### Event: `'drain'`
223+
224+
Emitted when pipeline is no longer busy.
225+
226+
See [Dispatcher Event: `'drain'`](/docs/docs/api/Dispatcher.md#event-drain).
227+
228+
#### Example - Client drain event
229+
230+
```js
231+
import { createServer } from "node:http2";
232+
import { H2CClient } from "undici";
233+
import { once } from "events";
234+
235+
const server = createServer((request, response) => {
236+
response.end("Hello, World!");
237+
}).listen();
238+
239+
await once(server, "listening");
240+
241+
const client = new H2CClient(`http://localhost:${server.address().port}`);
242+
243+
client.on("drain", () => {
244+
console.log("drain event");
245+
client.close();
246+
server.close();
247+
});
248+
249+
const requests = [
250+
client.request({ path: "/", method: "GET" }),
251+
client.request({ path: "/", method: "GET" }),
252+
client.request({ path: "/", method: "GET" }),
253+
];
254+
255+
await Promise.all(requests);
256+
257+
console.log("requests completed");
258+
```
259+
260+
### Event: `'error'`
261+
262+
Invoked for users errors such as throwing in the `onError` handler.

deps/undici/src/docs/docs/api/MockAgent.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ This method returns any pending interceptors registered on a mock agent. A pendi
477477

478478
Returns: `PendingInterceptor[]` (where `PendingInterceptor` is a `MockDispatch` with an additional `origin: string`)
479479

480-
#### Example - List all pending inteceptors
480+
#### Example - List all pending interceptors
481481

482482
```js
483483
const agent = new MockAgent()

deps/undici/src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const Agent = require('./lib/dispatcher/agent')
88
const ProxyAgent = require('./lib/dispatcher/proxy-agent')
99
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
1010
const RetryAgent = require('./lib/dispatcher/retry-agent')
11+
const H2CClient = require('./lib/dispatcher/h2c-client')
1112
const errors = require('./lib/core/errors')
1213
const util = require('./lib/core/util')
1314
const { InvalidArgumentError } = errors
@@ -33,6 +34,7 @@ module.exports.Agent = Agent
3334
module.exports.ProxyAgent = ProxyAgent
3435
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
3536
module.exports.RetryAgent = RetryAgent
37+
module.exports.H2CClient = H2CClient
3638
module.exports.RetryHandler = RetryHandler
3739

3840
module.exports.DecoratorHandler = DecoratorHandler

deps/undici/src/lib/cache/sqlite-cache-store.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ module.exports = class SqliteCacheStore {
115115
this.#db = new DatabaseSync(opts?.location ?? ':memory:')
116116

117117
this.#db.exec(`
118+
PRAGMA journal_mode = WAL;
119+
PRAGMA synchronous = NORMAL;
120+
PRAGMA temp_store = memory;
121+
PRAGMA optimize;
122+
118123
CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION} (
119124
-- Data specific to us
120125
id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -134,9 +139,8 @@ module.exports = class SqliteCacheStore {
134139
staleAt INTEGER NOT NULL
135140
);
136141
137-
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_url ON cacheInterceptorV${VERSION}(url);
138-
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_method ON cacheInterceptorV${VERSION}(method);
139-
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteAt ON cacheInterceptorV${VERSION}(deleteAt);
142+
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_getValuesQuery ON cacheInterceptorV${VERSION}(url, method, deleteAt);
143+
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION}_deleteByUrlQuery ON cacheInterceptorV${VERSION}(deleteAt);
140144
`)
141145

142146
this.#getValuesQuery = this.#db.prepare(`
@@ -346,7 +350,7 @@ module.exports = class SqliteCacheStore {
346350
}
347351

348352
#prune () {
349-
if (this.size <= this.#maxCount) {
353+
if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) {
350354
return 0
351355
}
352356

0 commit comments

Comments
 (0)