Skip to content

Commit 1d4c89e

Browse files
deps: update undici to 7.30.1
PR-URL: #66764 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
1 parent 0d10bfe commit 1d4c89e

33 files changed

Lines changed: 1392 additions & 714 deletions

‎deps/undici/src/docs/docs/api/Client.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Returns: `Client`
2727
* **webSocket** `WebSocketOptions` (optional) - WebSocket-specific configuration options.
2828
* **maxFragments** `number` (optional) - Default: `131072` - Maximum number of fragments in a message. Set to 0 to disable the limit.
2929
* **maxPayloadSize** `number` (optional) - Default: `134217728` (128 MB) - Maximum allowed payload size in bytes for WebSocket messages. Applied to uncompressed messages, compressed frame payloads, and decompressed (permessage-deflate) messages. Set to 0 to disable the limit.
30+
* **eventSource** `EventSourceOptions` (optional) - EventSource-specific configuration options.
31+
* **maxEventSize** `number` (optional) - The maximum total bytes of data and metadata field values retained for a pending EventSource event. Each unfinished line is separately limited to this value plus seven syntax bytes. The number of `data:` lines per event and input chunks buffered for an unfinished line are each limited to `min(131072, max(1024, floor(maxEventSize / 128)))` to bound object overhead. Set to `0` to disable these limits. Default: `buffer.kStringMaxLength`.
3032
* **pipelining** `number | null` (optional) - Default: `1` - 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). Carefully consider your workload and environment before enabling concurrent requests as pipelining may reduce performance if used incorrectly. Pipelining is sensitive to network stack settings as well as head of line blocking caused by e.g. long running requests. Set to `0` to disable keep-alive connections.
3133
* **connect** `ConnectOptions | Function | null` (optional) - Default: `null`.
3234
* **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. **Security Warning:** Disabling this option can expose your application to HTTP Request Smuggling attacks, where mismatched content-length headers cause servers and proxies to interpret request boundaries differently. This can lead to cache poisoning, credential hijacking, and bypassing security controls. Only disable this in controlled environments where you fully trust the request source.

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ diagnosticsChannel.channel('undici:request:bodySent').subscribe(({ request }) =>
5353

5454
## `undici:request:headers`
5555

56-
This message is published after the response headers have been received.
56+
This message is published after the response headers have been received. This includes a successful CONNECT or
57+
protocol upgrade response.
5758

5859
```js
5960
import diagnosticsChannel from 'diagnostics_channel'
@@ -82,6 +83,7 @@ diagnosticsChannel.channel('undici:request:bodyChunkReceived').subscribe(({ requ
8283
## `undici:request:trailers`
8384

8485
This message is published after the response body and trailers have been received, i.e. the response has been completed.
86+
After an upgraded socket is passed to the request handler, this message is published with an empty `trailers` array.
8587

8688
```js
8789
import diagnosticsChannel from 'diagnostics_channel'

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ The `decompress` interceptor automatically decompresses response bodies that are
11531153

11541154
- `skipErrorResponses` - Whether to skip decompression for error responses (status codes >= 400). Default: `true`.
11551155
- `skipStatusCodes` - Array of status codes to skip decompression for. Default: `[204, 304]`.
1156+
- `maxSize` - Maximum decompressed response size in bytes for each decompression stage. Set to `0` to disable the limit. Default: `0`.
11561157

11571158
**Example - Basic Decompress Interceptor**
11581159

‎deps/undici/src/lib/core/connect.js‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,22 @@ const SessionCache = class WeakSessionCache {
4141
if (this._sessionCache.has(sessionKey)) {
4242
this._sessionCache.delete(sessionKey)
4343
} else if (this._sessionCache.size >= this._maxCachedSessions) {
44+
// Make room for the new session: prefer an entry whose session has
45+
// already been collected, otherwise evict the oldest one.
46+
let evicted = false
4447
for (const [key, ref] of this._sessionCache) {
4548
if (ref.deref() === undefined) {
4649
this._sessionCache.delete(key)
47-
return
50+
evicted = true
51+
break
4852
}
4953
}
5054

51-
const oldest = this._sessionCache.keys().next()
52-
if (!oldest.done) {
53-
this._sessionCache.delete(oldest.value)
55+
if (!evicted) {
56+
const oldest = this._sessionCache.keys().next()
57+
if (!oldest.done) {
58+
this._sessionCache.delete(oldest.value)
59+
}
5460
}
5561
}
5662

‎deps/undici/src/lib/core/request.js‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,32 @@ class Request {
302302
}
303303
}
304304

305-
onUpgrade (statusCode, headers, socket) {
305+
/**
306+
* @param {number} statusCode
307+
* @param {Buffer[]|string[]} headers
308+
* @param {import('node:stream').Duplex} socket
309+
* @param {string} [statusText]
310+
*/
311+
onUpgrade (statusCode, headers, socket, statusText = '') {
312+
this.onFinally()
313+
306314
assert(!this.aborted)
307315
assert(!this.completed)
308316

309-
return this[kHandler].onUpgrade(statusCode, headers, socket)
317+
if (channels.headers.hasSubscribers) {
318+
channels.headers.publish({ request: this, response: { statusCode, headers, statusText } })
319+
}
320+
321+
const result = this[kHandler].onUpgrade(statusCode, headers, socket)
322+
323+
if (!this.aborted) {
324+
this.completed = true
325+
if (channels.trailers.hasSubscribers) {
326+
channels.trailers.publish({ request: this, trailers: [] })
327+
}
328+
}
329+
330+
return result
310331
}
311332

312333
onComplete (trailers) {

‎deps/undici/src/lib/core/symbols.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module.exports = {
55
kDestroy: Symbol('destroy'),
66
kDispatch: Symbol('dispatch'),
77
kUrl: Symbol('url'),
8+
kRedirectCacheControl: Symbol('redirect cache control'),
89
kWriting: Symbol('writing'),
910
kResuming: Symbol('resuming'),
1011
kQueue: Symbol('queue'),

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function defaultFactory (origin, opts) {
2222
}
2323

2424
class Agent extends DispatcherBase {
25-
constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) {
25+
constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, tls, ...options } = {}) {
2626
if (typeof factory !== 'function') {
2727
throw new InvalidArgumentError('factory must be a function.')
2828
}
@@ -41,7 +41,11 @@ class Agent extends DispatcherBase {
4141
connect = { ...connect }
4242
}
4343

44-
this[kOptions] = { ...util.deepClone(options), maxOrigins, connect }
44+
if (tls && typeof tls !== 'function') {
45+
tls = { ...tls }
46+
}
47+
48+
this[kOptions] = { ...util.deepClone(options), maxOrigins, connect, tls }
4549
this[kFactory] = factory
4650
this[kClients] = new Map()
4751
this[kOrigins] = new Set()

‎deps/undici/src/lib/dispatcher/client-h1.js‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,14 @@ function lazyllhttp () {
6969

7070
let mod
7171

72-
// We disable wasm SIMD on ppc64 as it seems to be broken on Power 9 architectures.
73-
let useWasmSIMD = process.arch !== 'ppc64'
72+
// We disable wasm SIMD on older versions of Node.js on ppc64 that are broken on Power >=9 architectures.
73+
let useWasmSIMD = true
74+
if (process.arch === 'ppc64') {
75+
const [major, minor] = process.versions.node.split('.').map(n => parseInt(n, 10))
76+
if (major < 24 || (major === 24 && minor < 12)) {
77+
useWasmSIMD = false
78+
}
79+
}
7480
// The Env Variable UNDICI_NO_WASM_SIMD allows explicitly overriding the default behavior
7581
if (process.env.UNDICI_NO_WASM_SIMD === '1') {
7682
useWasmSIMD = false
@@ -521,7 +527,7 @@ class Parser {
521527
* @param {Buffer} head
522528
*/
523529
onUpgrade (head) {
524-
const { upgrade, client, socket, headers, statusCode } = this
530+
const { upgrade, client, socket, headers, statusCode, statusText } = this
525531

526532
assert(upgrade)
527533
assert(client[kSocket] === socket)
@@ -556,8 +562,9 @@ class Parser {
556562
client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade'))
557563

558564
try {
559-
request.onUpgrade(statusCode, headers, socket)
565+
request.onUpgrade(statusCode, headers, socket, statusText)
560566
} catch (err) {
567+
util.errorRequest(client, request, err)
561568
util.destroy(socket, err)
562569
}
563570

@@ -921,8 +928,6 @@ function connectH1 (client, socket) {
921928
}
922929

923930
function onHttpSocketError (err) {
924-
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
925-
926931
const parser = this[kParser]
927932

928933
// On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,6 @@ function onHttp2SendPing (session) {
293293
}
294294

295295
function onHttp2SessionError (err) {
296-
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
297-
298296
this[kSocket][kError] = err
299297
this[kClient][kOnError](err)
300298
}
@@ -436,8 +434,6 @@ function onHttp2SocketClose () {
436434
}
437435

438436
function onHttp2SocketError (err) {
439-
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
440-
441437
this[kError] = err
442438

443439
this[kClient][kOnError](err)
@@ -575,13 +571,17 @@ function writeH2 (client, request) {
575571

576572
stream = session.request(headers, { endStream: false, signal })
577573
stream[kHTTP2Stream] = true
574+
++session[kOpenStreams]
578575

579576
stream.once('response', (headers, _flags) => {
580577
const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
581578

582-
request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream)
583-
584-
++session[kOpenStreams]
579+
try {
580+
request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream)
581+
} catch (err) {
582+
abort(err)
583+
return
584+
}
585585
completeRequest(client, request)
586586
})
587587

@@ -610,11 +610,16 @@ function writeH2 (client, request) {
610610
// We disabled endStream to allow the user to write to the stream
611611
stream = session.request(headers, { endStream: false, signal })
612612
stream[kHTTP2Stream] = true
613+
++session[kOpenStreams]
613614
stream.on('response', headers => {
614615
const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
615616

616-
request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream)
617-
++session[kOpenStreams]
617+
try {
618+
request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream)
619+
} catch (err) {
620+
abort(err)
621+
return
622+
}
618623
completeRequest(client, request)
619624
})
620625
stream.on('error', abort)

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ class Client extends DispatcherBase {
115115
initialWindowSize,
116116
connectionWindowSize,
117117
pingInterval,
118-
webSocket
118+
webSocket,
119+
eventSource
119120
} = {}) {
120121
if (keepAlive !== undefined) {
121122
throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead')
@@ -223,7 +224,7 @@ class Client extends DispatcherBase {
223224
throw new InvalidArgumentError('pingInterval must be a positive integer, greater or equal to 0')
224225
}
225226

226-
super({ webSocket })
227+
super({ webSocket, eventSource })
227228

228229
if (typeof connect !== 'function') {
229230
connect = buildConnector({

0 commit comments

Comments
 (0)