Skip to content

Commit b32b62d

Browse files
KhafraDevmarco-ippolito
authored andcommitted
deps: update undici to 6.15.0
PR-URL: #52763 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Marco Ippolito <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]> Reviewed-By: Filip Skokan <[email protected]> Reviewed-By: Ulises Gascón <[email protected]>
1 parent 6e6641b commit b32b62d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+9669
-9654
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Returns: `Client`
2323
* **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.
2424
* **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.
2525
* **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.
26-
* **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `1e3` - 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 1 second.
26+
* **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.
2727
* **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.
2828
* **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable.
2929
* **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.

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

+27-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# EventSource
22

3+
> ⚠️ Warning: the EventSource API is experimental.
4+
35
Undici exposes a WHATWG spec-compliant implementation of [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource)
46
for [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events).
57

@@ -11,11 +13,33 @@ follows:
1113
```mjs
1214
import { EventSource } from 'undici'
1315

14-
const evenSource = new EventSource('http://localhost:3000')
15-
evenSource.onmessage = (event) => {
16+
const eventSource = new EventSource('http://localhost:3000')
17+
eventSource.onmessage = (event) => {
1618
console.log(event.data)
1719
}
1820
```
1921

22+
## Using a custom Dispatcher
23+
24+
undici allows you to set your own Dispatcher in the EventSource constructor.
25+
26+
An example which allows you to modify the request headers is:
27+
28+
```mjs
29+
import { EventSource, Agent } from 'undici'
30+
31+
class CustomHeaderAgent extends Agent {
32+
dispatch (opts) {
33+
opts.headers['x-custom-header'] = 'hello world'
34+
return super.dispatch(...arguments)
35+
}
36+
}
37+
38+
const eventSource = new EventSource('http://localhost:3000', {
39+
dispatcher: new CustomHeaderAgent()
40+
})
41+
42+
```
43+
2044
More information about the EventSource API can be found on
21-
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventSource).
45+
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventSource).

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

-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ Undici exposes a fetch() method starts the process of fetching a resource from t
44

55
Documentation and examples can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/fetch).
66

7-
## File
8-
9-
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/File)
10-
11-
In Node versions v18.13.0 and above and v19.2.0 and above, undici will default to using Node's [File](https://nodejs.org/api/buffer.html#class-file) class. In versions where it's not available, it will default to the undici one.
12-
137
## FormData
148

159
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/FormData).

deps/undici/src/index-fetch.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict'
22

3+
const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global')
4+
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
35
const fetchImpl = require('./lib/web/fetch').fetch
46

57
module.exports.fetch = function fetch (resource, init = undefined) {
@@ -15,7 +17,16 @@ module.exports.Headers = require('./lib/web/fetch/headers').Headers
1517
module.exports.Response = require('./lib/web/fetch/response').Response
1618
module.exports.Request = require('./lib/web/fetch/request').Request
1719

20+
const { CloseEvent, ErrorEvent, MessageEvent, createFastMessageEvent } = require('./lib/web/websocket/events')
1821
module.exports.WebSocket = require('./lib/web/websocket/websocket').WebSocket
19-
module.exports.MessageEvent = require('./lib/web/websocket/events').MessageEvent
22+
module.exports.CloseEvent = CloseEvent
23+
module.exports.ErrorEvent = ErrorEvent
24+
module.exports.MessageEvent = MessageEvent
25+
module.exports.createFastMessageEvent = createFastMessageEvent
2026

2127
module.exports.EventSource = require('./lib/web/eventsource/eventsource').EventSource
28+
29+
// Expose the fetch implementation to be enabled in Node.js core via a flag
30+
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
31+
module.exports.getGlobalDispatcher = getGlobalDispatcher
32+
module.exports.setGlobalDispatcher = setGlobalDispatcher

deps/undici/src/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const Pool = require('./lib/dispatcher/pool')
66
const BalancedPool = require('./lib/dispatcher/balanced-pool')
77
const Agent = require('./lib/dispatcher/agent')
88
const ProxyAgent = require('./lib/dispatcher/proxy-agent')
9+
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
910
const RetryAgent = require('./lib/dispatcher/retry-agent')
1011
const errors = require('./lib/core/errors')
1112
const util = require('./lib/core/util')
@@ -30,6 +31,7 @@ module.exports.Pool = Pool
3031
module.exports.BalancedPool = BalancedPool
3132
module.exports.Agent = Agent
3233
module.exports.ProxyAgent = ProxyAgent
34+
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
3335
module.exports.RetryAgent = RetryAgent
3436
module.exports.RetryHandler = RetryHandler
3537

@@ -116,7 +118,7 @@ module.exports.Headers = require('./lib/web/fetch/headers').Headers
116118
module.exports.Response = require('./lib/web/fetch/response').Response
117119
module.exports.Request = require('./lib/web/fetch/request').Request
118120
module.exports.FormData = require('./lib/web/fetch/formdata').FormData
119-
module.exports.File = require('./lib/web/fetch/file').File
121+
module.exports.File = globalThis.File ?? require('node:buffer').File
120122
module.exports.FileReader = require('./lib/web/fileapi/filereader').FileReader
121123

122124
const { setGlobalOrigin, getGlobalOrigin } = require('./lib/web/fetch/global')

deps/undici/src/lib/api/util.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,25 @@ async function getResolveErrorBodyCallback ({ callback, body, contentType, statu
1212
let chunks = []
1313
let length = 0
1414

15-
for await (const chunk of body) {
16-
chunks.push(chunk)
17-
length += chunk.length
18-
if (length > CHUNK_LIMIT) {
19-
chunks = null
20-
break
15+
try {
16+
for await (const chunk of body) {
17+
chunks.push(chunk)
18+
length += chunk.length
19+
if (length > CHUNK_LIMIT) {
20+
chunks = []
21+
length = 0
22+
break
23+
}
2124
}
25+
} catch {
26+
chunks = []
27+
length = 0
28+
// Do nothing....
2229
}
2330

2431
const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`
2532

26-
if (statusCode === 204 || !contentType || !chunks) {
33+
if (statusCode === 204 || !contentType || !length) {
2734
queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers)))
2835
return
2936
}

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

+3-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const {
77
const assert = require('node:assert')
88
const {
99
isValidHTTPToken,
10-
isValidHeaderChar,
10+
isValidHeaderValue,
1111
isStream,
1212
destroy,
1313
isBuffer,
@@ -336,7 +336,7 @@ function processHeader (request, key, val) {
336336
const arr = []
337337
for (let i = 0; i < val.length; i++) {
338338
if (typeof val[i] === 'string') {
339-
if (!isValidHeaderChar(val[i])) {
339+
if (!isValidHeaderValue(val[i])) {
340340
throw new InvalidArgumentError(`invalid ${key} header`)
341341
}
342342
arr.push(val[i])
@@ -350,13 +350,11 @@ function processHeader (request, key, val) {
350350
}
351351
val = arr
352352
} else if (typeof val === 'string') {
353-
if (!isValidHeaderChar(val)) {
353+
if (!isValidHeaderValue(val)) {
354354
throw new InvalidArgumentError(`invalid ${key} header`)
355355
}
356356
} else if (val === null) {
357357
val = ''
358-
} else if (typeof val === 'object') {
359-
throw new InvalidArgumentError(`invalid ${key} header`)
360358
} else {
361359
val = `${val}`
362360
}

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,8 @@ module.exports = {
6060
kConstruct: Symbol('constructable'),
6161
kListeners: Symbol('listeners'),
6262
kHTTPContext: Symbol('http context'),
63-
kMaxConcurrentStreams: Symbol('max concurrent streams')
63+
kMaxConcurrentStreams: Symbol('max concurrent streams'),
64+
kNoProxyAgent: Symbol('no proxy agent'),
65+
kHttpProxyAgent: Symbol('http proxy agent'),
66+
kHttpsProxyAgent: Symbol('https proxy agent')
6467
}

deps/undici/src/lib/core/util.js

+45-20
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,37 @@ function buildURL (url, queryParams) {
5252
return url
5353
}
5454

55+
function isValidPort (port) {
56+
const value = parseInt(port, 10)
57+
return (
58+
value === Number(port) &&
59+
value >= 0 &&
60+
value <= 65535
61+
)
62+
}
63+
64+
function isHttpOrHttpsPrefixed (value) {
65+
return (
66+
value != null &&
67+
value[0] === 'h' &&
68+
value[1] === 't' &&
69+
value[2] === 't' &&
70+
value[3] === 'p' &&
71+
(
72+
value[4] === ':' ||
73+
(
74+
value[4] === 's' &&
75+
value[5] === ':'
76+
)
77+
)
78+
)
79+
}
80+
5581
function parseURL (url) {
5682
if (typeof url === 'string') {
5783
url = new URL(url)
5884

59-
if (!/^https?:/.test(url.origin || url.protocol)) {
85+
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
6086
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
6187
}
6288

@@ -67,12 +93,8 @@ function parseURL (url) {
6793
throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.')
6894
}
6995

70-
if (!/^https?:/.test(url.origin || url.protocol)) {
71-
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
72-
}
73-
7496
if (!(url instanceof URL)) {
75-
if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) {
97+
if (url.port != null && url.port !== '' && isValidPort(url.port) === false) {
7698
throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.')
7799
}
78100

@@ -92,28 +114,36 @@ function parseURL (url) {
92114
throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.')
93115
}
94116

117+
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
118+
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
119+
}
120+
95121
const port = url.port != null
96122
? url.port
97123
: (url.protocol === 'https:' ? 443 : 80)
98124
let origin = url.origin != null
99125
? url.origin
100-
: `${url.protocol}//${url.hostname}:${port}`
126+
: `${url.protocol || ''}//${url.hostname || ''}:${port}`
101127
let path = url.path != null
102128
? url.path
103129
: `${url.pathname || ''}${url.search || ''}`
104130

105-
if (origin.endsWith('/')) {
106-
origin = origin.substring(0, origin.length - 1)
131+
if (origin[origin.length - 1] === '/') {
132+
origin = origin.slice(0, origin.length - 1)
107133
}
108134

109-
if (path && !path.startsWith('/')) {
135+
if (path && path[0] !== '/') {
110136
path = `/${path}`
111137
}
112138
// new URL(path, origin) is unsafe when `path` contains an absolute URL
113139
// From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL:
114140
// If first parameter is a relative URL, second param is required, and will be used as the base URL.
115141
// If first parameter is an absolute URL, a given second param will be ignored.
116-
url = new URL(origin + path)
142+
return new URL(`${origin}${path}`)
143+
}
144+
145+
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
146+
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
117147
}
118148

119149
return url
@@ -193,11 +223,6 @@ function isDestroyed (body) {
193223
return body && !!(body.destroyed || body[kDestroyed] || (stream.isDestroyed?.(body)))
194224
}
195225

196-
function isReadableAborted (stream) {
197-
const state = stream?._readableState
198-
return isDestroyed(stream) && state && !state.endEmitted
199-
}
200-
201226
function destroy (stream, err) {
202227
if (stream == null || !isStream(stream) || isDestroyed(stream)) {
203228
return
@@ -522,7 +547,7 @@ const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/
522547
/**
523548
* @param {string} characters
524549
*/
525-
function isValidHeaderChar (characters) {
550+
function isValidHeaderValue (characters) {
526551
return !headerCharRegex.test(characters)
527552
}
528553

@@ -575,7 +600,6 @@ module.exports = {
575600
isReadable,
576601
toUSVString,
577602
isUSVString,
578-
isReadableAborted,
579603
isBlobLike,
580604
parseOrigin,
581605
parseURL,
@@ -603,11 +627,12 @@ module.exports = {
603627
buildURL,
604628
addAbortListener,
605629
isValidHTTPToken,
606-
isValidHeaderChar,
630+
isValidHeaderValue,
607631
isTokenCharCode,
608632
parseRangeHeader,
633+
isValidPort,
634+
isHttpOrHttpsPrefixed,
609635
nodeMajor,
610636
nodeMinor,
611-
nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13),
612637
safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE']
613638
}

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

+2-4
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,9 @@ function onHttp2SessionEnd () {
208208
* This is the root cause of #3011
209209
* We need to handle GOAWAY frames properly, and trigger the session close
210210
* along with the socket right away
211-
* Find a way to trigger the close cycle from here on.
212211
*/
213212
function onHTTP2GoAway (code) {
214-
const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`)
213+
const err = new RequestAbortedError(`HTTP/2: "GOAWAY" frame received with code ${code}`)
215214

216215
// We need to trigger the close cycle right away
217216
// We need to destroy the session and the socket
@@ -220,8 +219,7 @@ function onHTTP2GoAway (code) {
220219
this[kClient][kOnError](err)
221220

222221
this.unref()
223-
// We send the GOAWAY frame response as no error
224-
this.destroy()
222+
225223
util.destroy(this[kSocket], err)
226224
}
227225

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ class Client extends DispatcherBase {
203203
allowH2,
204204
socketPath,
205205
timeout: connectTimeout,
206-
...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
206+
...(autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
207207
...connect
208208
})
209209
}
@@ -226,7 +226,7 @@ class Client extends DispatcherBase {
226226
this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize
227227
this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout
228228
this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout
229-
this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold
229+
this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 2e3 : keepAliveTimeoutThreshold
230230
this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout]
231231
this[kServerName] = null
232232
this[kLocalAddress] = localAddress != null ? localAddress : null
@@ -376,6 +376,7 @@ function onError (client, err) {
376376
assert(client[kPendingIdx] === client[kRunningIdx])
377377

378378
const requests = client[kQueue].splice(client[kRunningIdx])
379+
379380
for (let i = 0; i < requests.length; i++) {
380381
const request = requests[i]
381382
util.errorRequest(client, request, err)

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ const {
66
ClientClosedError,
77
InvalidArgumentError
88
} = require('../core/errors')
9-
const { kDestroy, kClose, kDispatch, kInterceptors } = require('../core/symbols')
9+
const { kDestroy, kClose, kClosed, kDestroyed, kDispatch, kInterceptors } = require('../core/symbols')
1010

11-
const kDestroyed = Symbol('destroyed')
12-
const kClosed = Symbol('closed')
1311
const kOnDestroyed = Symbol('onDestroyed')
1412
const kOnClosed = Symbol('onClosed')
1513
const kInterceptedDispatch = Symbol('Intercepted Dispatch')

0 commit comments

Comments
 (0)