Skip to content

Commit 1091066

Browse files
nodejs-github-bottargos
authored andcommitted
deps: update undici to 7.9.0
PR-URL: #58268 Reviewed-By: Matthew Aitken <[email protected]> Reviewed-By: Michaël Zasso <[email protected]>
1 parent b0e0b1a commit 1091066

26 files changed

+793
-620
lines changed

deps/undici/src/README.md

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,22 @@ const readableWebStream = response.body
261261
const readableNodeStream = Readable.fromWeb(readableWebStream)
262262
```
263263

264-
#### Specification Compliance
264+
## Specification Compliance
265265

266-
This section documents parts of the [Fetch Standard](https://fetch.spec.whatwg.org) that Undici does
266+
This section documents parts of the [HTTP/1.1](https://www.rfc-editor.org/rfc/rfc9110.html) and [Fetch Standard](https://fetch.spec.whatwg.org) that Undici does
267267
not support or does not fully implement.
268268

269-
##### Garbage Collection
269+
#### CORS
270+
271+
Unlike browsers, Undici does not implement CORS (Cross-Origin Resource Sharing) checks by default. This means:
272+
273+
- No preflight requests are automatically sent for cross-origin requests
274+
- No validation of `Access-Control-Allow-Origin` headers is performed
275+
- Requests to any origin are allowed regardless of the source
276+
277+
This behavior is intentional for server-side environments where CORS restrictions are typically unnecessary. If your application requires CORS-like protections, you will need to implement these checks manually.
278+
279+
#### Garbage Collection
270280

271281
* https://fetch.spec.whatwg.org/#garbage-collection
272282

@@ -307,7 +317,7 @@ const headers = await fetch(url, { method: 'HEAD' })
307317
.then(res => res.headers)
308318
```
309319

310-
##### Forbidden and Safelisted Header Names
320+
#### Forbidden and Safelisted Header Names
311321

312322
* https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
313323
* https://fetch.spec.whatwg.org/#forbidden-header-name
@@ -316,7 +326,7 @@ const headers = await fetch(url, { method: 'HEAD' })
316326

317327
The [Fetch Standard](https://fetch.spec.whatwg.org) requires implementations to exclude certain headers from requests and responses. In browser environments, some headers are forbidden so the user agent remains in full control over them. In Undici, these constraints are removed to give more control to the user.
318328

319-
### `undici.upgrade([url, options]): Promise`
329+
#### `undici.upgrade([url, options]): Promise`
320330

321331
Upgrade to a different protocol. See [MDN - HTTP - Protocol upgrade mechanism](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) for more details.
322332

@@ -378,20 +388,15 @@ Returns: `URL`
378388
* **protocol** `string` (optional)
379389
* **search** `string` (optional)
380390

381-
## Specification Compliance
382-
383-
This section documents parts of the HTTP/1.1 specification that Undici does
384-
not support or does not fully implement.
385-
386-
### Expect
391+
#### Expect
387392

388393
Undici does not support the `Expect` request header field. The request
389394
body is always immediately sent and the `100 Continue` response will be
390395
ignored.
391396

392397
Refs: https://tools.ietf.org/html/rfc7231#section-5.1.1
393398

394-
### Pipelining
399+
#### Pipelining
395400

396401
Undici will only use pipelining if configured with a `pipelining` factor
397402
greater than `1`. Also it is important to pass `blocking: false` to the
@@ -412,7 +417,7 @@ aborted.
412417
* Refs: https://tools.ietf.org/html/rfc2616#section-8.1.2.2
413418
* Refs: https://tools.ietf.org/html/rfc7230#section-6.3.2
414419

415-
### Manual Redirect
420+
#### Manual Redirect
416421

417422
Since it is not possible to manually follow an HTTP redirect on the server-side,
418423
Undici returns the actual response instead of an `opaqueredirect` filtered one
@@ -421,9 +426,9 @@ implementations in Deno and Cloudflare Workers.
421426

422427
Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling
423428

424-
## Workarounds
429+
### Workarounds
425430

426-
### Network address family autoselection.
431+
#### Network address family autoselection.
427432

428433
If you experience problem when connecting to a remote server that is resolved by your DNS servers to a IPv6 (AAAA record)
429434
first, there are chances that your local router or ISP might have problem connecting to IPv6 networks. In that case

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,9 @@ See [`Dispatcher.stream(options, factory[, callback])`](/docs/docs/api/Dispatche
7575
### `Agent.upgrade(options[, callback])`
7676

7777
See [`Dispatcher.upgrade(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback).
78+
79+
### `Agent.stats()`
80+
81+
Returns an object of stats by origin in the format of `Record<string, TClientStats | TPoolStats>`
82+
83+
See [`PoolStats`](/docs/docs/api/PoolStats.md) and [`ClientStats`](/docs/docs/api/ClientStats.md).
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Class: ClientStats
2+
3+
Stats for a [Client](/docs/docs/api/Client.md).
4+
5+
## `new ClientStats(client)`
6+
7+
Arguments:
8+
9+
* **client** `Client` - Client from which to return stats.
10+
11+
## Instance Properties
12+
13+
### `ClientStats.connected`
14+
15+
Boolean if socket as open connection by this client.
16+
17+
### `ClientStats.pending`
18+
19+
Number of pending requests of this client.
20+
21+
### `ClientStats.running`
22+
23+
Number of currently active requests across this client.
24+
25+
### `ClientStats.size`
26+
27+
Number of active, pending, or queued requests of this clients.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
1919
console.log('completed', request.completed)
2020
console.log('method', request.method)
2121
console.log('path', request.path)
22-
console.log('headers') // array of strings, e.g: ['foo', 'bar']
22+
console.log('headers', request.headers) // array of strings, e.g: ['foo', 'bar']
2323
request.addHeader('hello', 'world')
2424
console.log('headers', request.headers) // e.g. ['foo', 'bar', 'hello', 'world']
2525
})

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Extends: [`AgentOptions`](/docs/docs/api/Agent.md#parameter-agentoptions)
2020

2121
* **ignoreTrailingSlash** `boolean` (optional) - Default: `false` - set the default value for `ignoreTrailingSlash` for interceptors.
2222

23+
* **acceptNonStandardSearchParameters** `boolean` (optional) - Default: `false` - set to `true` if the matcher should also accept non standard search parameters such as multi-value items specified with `[]` (e.g. `param[]=1&param[]=2&param[]=3`) and multi-value items which values are comma separated (e.g. `param=1,2,3`).
24+
2325
### Example - Basic MockAgent instantiation
2426

2527
This will instantiate the MockAgent. It will not do anything until registered as the agent to use with requests and mock interceptions are added.

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

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,9 @@ class MemoryCacheStore {
7676
const topLevelKey = `${key.origin}:${key.path}`
7777

7878
const now = Date.now()
79-
const entry = this.#entries.get(topLevelKey)?.find((entry) => (
80-
entry.deleteAt > now &&
81-
entry.method === key.method &&
82-
(entry.vary == null || Object.keys(entry.vary).every(headerName => {
83-
if (entry.vary[headerName] === null) {
84-
return key.headers[headerName] === undefined
85-
}
79+
const entries = this.#entries.get(topLevelKey)
8680

87-
return entry.vary[headerName] === key.headers[headerName]
88-
}))
89-
))
81+
const entry = entries ? findEntry(key, entries, now) : null
9082

9183
return entry == null
9284
? undefined
@@ -140,10 +132,17 @@ class MemoryCacheStore {
140132
entries = []
141133
store.#entries.set(topLevelKey, entries)
142134
}
143-
entries.push(entry)
135+
const previousEntry = findEntry(key, entries, Date.now())
136+
if (previousEntry) {
137+
const index = entries.indexOf(previousEntry)
138+
entries.splice(index, 1, entry)
139+
store.#size -= previousEntry.size
140+
} else {
141+
entries.push(entry)
142+
store.#count += 1
143+
}
144144

145145
store.#size += entry.size
146-
store.#count += 1
147146

148147
if (store.#size > store.#maxSize || store.#count > store.#maxCount) {
149148
for (const [key, entries] of store.#entries) {
@@ -180,4 +179,18 @@ class MemoryCacheStore {
180179
}
181180
}
182181

182+
function findEntry (key, entries, now) {
183+
return entries.find((entry) => (
184+
entry.deleteAt > now &&
185+
entry.method === key.method &&
186+
(entry.vary == null || Object.keys(entry.vary).every(headerName => {
187+
if (entry.vary[headerName] === null) {
188+
return key.headers[headerName] === undefined
189+
}
190+
191+
return entry.vary[headerName] === key.headers[headerName]
192+
}))
193+
))
194+
}
195+
183196
module.exports = MemoryCacheStore

deps/undici/src/lib/dispatcher/agent.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const { InvalidArgumentError } = require('../core/errors')
4-
const { kClients, kRunning, kClose, kDestroy, kDispatch } = require('../core/symbols')
4+
const { kClients, kRunning, kClose, kDestroy, kDispatch, kUrl } = require('../core/symbols')
55
const DispatcherBase = require('./dispatcher-base')
66
const Pool = require('./pool')
77
const Client = require('./client')
@@ -110,6 +110,16 @@ class Agent extends DispatcherBase {
110110

111111
await Promise.all(destroyPromises)
112112
}
113+
114+
get stats () {
115+
const allClientStats = {}
116+
for (const client of this[kClients].values()) {
117+
if (client.stats) {
118+
allClientStats[client[kUrl].origin] = client.stats
119+
}
120+
}
121+
return allClientStats
122+
}
113123
}
114124

115125
module.exports = Agent

deps/undici/src/lib/dispatcher/client-h2.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,13 @@ function writeH2 (client, request) {
295295
if (Array.isArray(val)) {
296296
for (let i = 0; i < val.length; i++) {
297297
if (headers[key]) {
298-
headers[key] += `,${val[i]}`
298+
headers[key] += `, ${val[i]}`
299299
} else {
300300
headers[key] = val[i]
301301
}
302302
}
303+
} else if (headers[key]) {
304+
headers[key] += `, ${val}`
303305
} else {
304306
headers[key] = val
305307
}

deps/undici/src/lib/dispatcher/client.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const assert = require('node:assert')
44
const net = require('node:net')
55
const http = require('node:http')
66
const util = require('../core/util.js')
7+
const { ClientStats } = require('../util/stats.js')
78
const { channels } = require('../core/diagnostics.js')
89
const Request = require('../core/request.js')
910
const DispatcherBase = require('./dispatcher-base')
@@ -260,6 +261,10 @@ class Client extends DispatcherBase {
260261
this[kResume](true)
261262
}
262263

264+
get stats () {
265+
return new ClientStats(this)
266+
}
267+
263268
get [kPending] () {
264269
return this[kQueue].length - this[kPendingIdx]
265270
}

deps/undici/src/lib/dispatcher/pool-base.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
'use strict'
22

3+
const { PoolStats } = require('../util/stats.js')
34
const DispatcherBase = require('./dispatcher-base')
45
const FixedQueue = require('./fixed-queue')
56
const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = require('../core/symbols')
6-
const PoolStats = require('./pool-stats')
77

88
const kClients = Symbol('clients')
99
const kNeedDrain = Symbol('needDrain')
@@ -16,7 +16,6 @@ const kOnConnectionError = Symbol('onConnectionError')
1616
const kGetDispatcher = Symbol('get dispatcher')
1717
const kAddClient = Symbol('add client')
1818
const kRemoveClient = Symbol('remove client')
19-
const kStats = Symbol('stats')
2019

2120
class PoolBase extends DispatcherBase {
2221
constructor () {
@@ -67,8 +66,6 @@ class PoolBase extends DispatcherBase {
6766
this[kOnConnectionError] = (origin, targets, err) => {
6867
pool.emit('connectionError', origin, [pool, ...targets], err)
6968
}
70-
71-
this[kStats] = new PoolStats(this)
7269
}
7370

7471
get [kBusy] () {
@@ -108,7 +105,7 @@ class PoolBase extends DispatcherBase {
108105
}
109106

110107
get stats () {
111-
return this[kStats]
108+
return new PoolStats(this)
112109
}
113110

114111
async [kClose] () {

deps/undici/src/lib/dispatcher/pool-stats.js

Lines changed: 0 additions & 36 deletions
This file was deleted.

deps/undici/src/lib/interceptor/cache.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ const { AbortError } = require('../core/errors.js')
2020
*/
2121
function needsRevalidation (result, cacheControlDirectives) {
2222
if (cacheControlDirectives?.['no-cache']) {
23-
// Always revalidate requests with the no-cache directive
23+
// Always revalidate requests with the no-cache request directive
24+
return true
25+
}
26+
27+
if (result.cacheControlDirectives?.['no-cache'] && !Array.isArray(result.cacheControlDirectives['no-cache'])) {
28+
// Always revalidate requests with unqualified no-cache response directive
2429
return true
2530
}
2631

@@ -233,7 +238,7 @@ function handleResult (
233238
}
234239

235240
let headers = {
236-
...normaliseHeaders(opts),
241+
...opts.headers,
237242
'if-modified-since': new Date(result.cachedAt).toUTCString()
238243
}
239244

@@ -319,6 +324,11 @@ module.exports = (opts = {}) => {
319324
return dispatch(opts, handler)
320325
}
321326

327+
opts = {
328+
...opts,
329+
headers: normaliseHeaders(opts)
330+
}
331+
322332
const reqCacheControl = opts.headers?.['cache-control']
323333
? parseCacheControlHeader(opts.headers['cache-control'])
324334
: undefined

deps/undici/src/lib/llhttp/wasm_build_env.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
> undici@7.8.0 build:wasm
2+
> undici@7.9.0 build:wasm
33
> node build/wasm.js --docker
44

55
> 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

0 commit comments

Comments
 (0)