Skip to content

Commit 84f5a1f

Browse files
nodejs-github-bottargos
authored andcommitted
deps: update undici to 5.21.0
PR-URL: #47063 Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
1 parent ed31316 commit 84f5a1f

23 files changed

+542
-356
lines changed

deps/undici/src/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling
407407

408408
## Workarounds
409409

410-
### Network address family autoselection.
410+
### Network address family autoselection.
411411

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

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Extends: [`AgentOptions`](Agent.md#parameter-agentoptions)
1919
* **uri** `string` (required) - It can be passed either by a string or a object containing `uri` as string.
2020
* **token** `string` (optional) - It can be passed by a string of token for authentication.
2121
* **auth** `string` (**deprecated**) - Use token.
22+
* **clientFactory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Pool(origin, opts)`
2223

2324
Examples:
2425

@@ -83,7 +84,8 @@ import { setGlobalDispatcher, request, ProxyAgent } from 'undici';
8384

8485
const proxyAgent = new ProxyAgent({
8586
uri: 'my.proxy.server',
86-
token: 'Bearer xxxx'
87+
// token: 'Bearer xxxx'
88+
token: `Basic ${Buffer.from('username:password').toString('base64')}`
8789
});
8890
setGlobalDispatcher(proxyAgent);
8991

deps/undici/src/lib/api/api-stream.js

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

3-
const { finished } = require('stream')
3+
const { finished, PassThrough } = require('stream')
44
const {
55
InvalidArgumentError,
66
InvalidReturnValueError,
7-
RequestAbortedError
7+
RequestAbortedError,
8+
ResponseStatusCodeError
89
} = require('../core/errors')
910
const util = require('../core/util')
1011
const { AsyncResource } = require('async_hooks')
@@ -16,7 +17,7 @@ class StreamHandler extends AsyncResource {
1617
throw new InvalidArgumentError('invalid opts')
1718
}
1819

19-
const { signal, method, opaque, body, onInfo, responseHeaders } = opts
20+
const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts
2021

2122
try {
2223
if (typeof callback !== 'function') {
@@ -57,6 +58,7 @@ class StreamHandler extends AsyncResource {
5758
this.trailers = null
5859
this.body = body
5960
this.onInfo = onInfo || null
61+
this.throwOnError = throwOnError || false
6062

6163
if (util.isStream(body)) {
6264
body.on('error', (err) => {
@@ -76,8 +78,8 @@ class StreamHandler extends AsyncResource {
7678
this.context = context
7779
}
7880

79-
onHeaders (statusCode, rawHeaders, resume) {
80-
const { factory, opaque, context } = this
81+
onHeaders (statusCode, rawHeaders, resume, statusMessage) {
82+
const { factory, opaque, context, callback } = this
8183

8284
if (statusCode < 200) {
8385
if (this.onInfo) {
@@ -96,6 +98,32 @@ class StreamHandler extends AsyncResource {
9698
context
9799
})
98100

101+
if (this.throwOnError && statusCode >= 400) {
102+
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
103+
const chunks = []
104+
const pt = new PassThrough()
105+
pt
106+
.on('data', (chunk) => chunks.push(chunk))
107+
.on('end', () => {
108+
const payload = Buffer.concat(chunks).toString('utf8')
109+
this.runInAsyncScope(
110+
callback,
111+
null,
112+
new ResponseStatusCodeError(
113+
`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`,
114+
statusCode,
115+
headers,
116+
payload
117+
)
118+
)
119+
})
120+
.on('error', (err) => {
121+
this.onError(err)
122+
})
123+
this.res = pt
124+
return
125+
}
126+
99127
if (
100128
!res ||
101129
typeof res.write !== 'function' ||

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

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
const assert = require('assert')
66
const { Readable } = require('stream')
7-
const { RequestAbortedError, NotSupportedError } = require('../core/errors')
7+
const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = require('../core/errors')
88
const util = require('../core/util')
99
const { ReadableStreamFrom, toUSVString } = require('../core/util')
1010

@@ -146,15 +146,31 @@ module.exports = class BodyReadable extends Readable {
146146

147147
async dump (opts) {
148148
let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144
149+
const signal = opts && opts.signal
150+
const abortFn = () => {
151+
this.destroy()
152+
}
153+
if (signal) {
154+
if (typeof signal !== 'object' || !('aborted' in signal)) {
155+
throw new InvalidArgumentError('signal must be an AbortSignal')
156+
}
157+
util.throwIfAborted(signal)
158+
signal.addEventListener('abort', abortFn, { once: true })
159+
}
149160
try {
150161
for await (const chunk of this) {
162+
util.throwIfAborted(signal)
151163
limit -= Buffer.byteLength(chunk)
152164
if (limit < 0) {
153165
return
154166
}
155167
}
156168
} catch {
157-
// Do nothing...
169+
util.throwIfAborted(signal)
170+
} finally {
171+
if (signal) {
172+
signal.removeEventListener('abort', abortFn)
173+
}
158174
}
159175
}
160176
}

deps/undici/src/lib/client.js

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// @ts-check
2+
13
'use strict'
24

35
/* global WebAssembly */
@@ -85,7 +87,15 @@ try {
8587
channels.connected = { hasSubscribers: false }
8688
}
8789

90+
/**
91+
* @type {import('../types/client').default}
92+
*/
8893
class Client extends DispatcherBase {
94+
/**
95+
*
96+
* @param {string|URL} url
97+
* @param {import('../types/client').Client.Options} options
98+
*/
8999
constructor (url, {
90100
interceptors,
91101
maxHeaderSize,
@@ -1658,6 +1668,8 @@ class AsyncWriter {
16581668
process.emitWarning(new RequestContentLengthMismatchError())
16591669
}
16601670

1671+
socket.cork()
1672+
16611673
if (bytesWritten === 0) {
16621674
if (!expectsPayload) {
16631675
socket[kReset] = true
@@ -1678,6 +1690,8 @@ class AsyncWriter {
16781690

16791691
const ret = socket.write(chunk)
16801692

1693+
socket.uncork()
1694+
16811695
request.onBodySent(chunk)
16821696

16831697
if (!ret) {

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

+33-15
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(
1515
function nop () {}
1616

1717
function isStream (obj) {
18-
return obj && typeof obj.pipe === 'function'
18+
return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function'
1919
}
2020

2121
// based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License)
@@ -46,6 +46,12 @@ function buildURL (url, queryParams) {
4646
function parseURL (url) {
4747
if (typeof url === 'string') {
4848
url = new URL(url)
49+
50+
if (!/^https?:/.test(url.origin || url.protocol)) {
51+
throw new InvalidArgumentError('invalid protocol')
52+
}
53+
54+
return url
4955
}
5056

5157
if (!url || typeof url !== 'object') {
@@ -375,23 +381,34 @@ function ReadableStreamFrom (iterable) {
375381

376382
// The chunk should be a FormData instance and contains
377383
// all the required methods.
378-
function isFormDataLike (chunk) {
379-
return (chunk &&
380-
chunk.constructor && chunk.constructor.name === 'FormData' &&
381-
typeof chunk === 'object' &&
382-
(typeof chunk.append === 'function' &&
383-
typeof chunk.delete === 'function' &&
384-
typeof chunk.get === 'function' &&
385-
typeof chunk.getAll === 'function' &&
386-
typeof chunk.has === 'function' &&
387-
typeof chunk.set === 'function' &&
388-
typeof chunk.entries === 'function' &&
389-
typeof chunk.keys === 'function' &&
390-
typeof chunk.values === 'function' &&
391-
typeof chunk.forEach === 'function')
384+
function isFormDataLike (object) {
385+
return (
386+
object &&
387+
typeof object === 'object' &&
388+
typeof object.append === 'function' &&
389+
typeof object.delete === 'function' &&
390+
typeof object.get === 'function' &&
391+
typeof object.getAll === 'function' &&
392+
typeof object.has === 'function' &&
393+
typeof object.set === 'function' &&
394+
object[Symbol.toStringTag] === 'FormData'
392395
)
393396
}
394397

398+
function throwIfAborted (signal) {
399+
if (!signal) { return }
400+
if (typeof signal.throwIfAborted === 'function') {
401+
signal.throwIfAborted()
402+
} else {
403+
if (signal.aborted) {
404+
// DOMException not available < v17.0.0
405+
const err = new Error('The operation was aborted')
406+
err.name = 'AbortError'
407+
throw err
408+
}
409+
}
410+
}
411+
395412
const kEnumerableProperty = Object.create(null)
396413
kEnumerableProperty.enumerable = true
397414

@@ -423,6 +440,7 @@ module.exports = {
423440
getSocketInfo,
424441
isFormDataLike,
425442
buildURL,
443+
throwIfAborted,
426444
nodeMajor,
427445
nodeMinor,
428446
nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13)

deps/undici/src/lib/fetch/dataURL.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const assert = require('assert')
22
const { atob } = require('buffer')
3-
const { format } = require('url')
43
const { isValidHTTPToken, isomorphicDecode } = require('./util')
54

65
const encoder = new TextEncoder()
@@ -118,7 +117,17 @@ function dataURLProcessor (dataURL) {
118117
* @param {boolean} excludeFragment
119118
*/
120119
function URLSerializer (url, excludeFragment = false) {
121-
return format(url, { fragment: !excludeFragment })
120+
const href = url.href
121+
122+
if (!excludeFragment) {
123+
return href
124+
}
125+
126+
const hash = href.lastIndexOf('#')
127+
if (hash === -1) {
128+
return href
129+
}
130+
return href.slice(0, hash)
122131
}
123132

124133
// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points

deps/undici/src/lib/fetch/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ function finalizeAndReportTiming (response, initiatorType = 'other') {
297297
// capability.
298298
// TODO: given global’s relevant settings object’s cross-origin isolated
299299
// capability?
300-
response.timingInfo.endTime = coarsenedSharedCurrentTime()
300+
timingInfo.endTime = coarsenedSharedCurrentTime()
301301

302302
// 10. Set response’s timing info to timingInfo.
303303
response.timingInfo = timingInfo

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

+16-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ const util = require('../core/util')
99
const {
1010
isValidHTTPToken,
1111
sameOrigin,
12-
normalizeMethod
12+
normalizeMethod,
13+
makePolicyContainer
1314
} = require('./util')
1415
const {
1516
forbiddenMethods,
@@ -51,10 +52,14 @@ class Request {
5152
input = webidl.converters.RequestInfo(input)
5253
init = webidl.converters.RequestInit(init)
5354

54-
// TODO
55+
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
5556
this[kRealm] = {
5657
settingsObject: {
57-
baseUrl: getGlobalOrigin()
58+
baseUrl: getGlobalOrigin(),
59+
get origin () {
60+
return this.baseUrl?.origin
61+
},
62+
policyContainer: makePolicyContainer()
5863
}
5964
}
6065

@@ -349,14 +354,17 @@ class Request {
349354
if (signal.aborted) {
350355
ac.abort(signal.reason)
351356
} else {
352-
const acRef = new WeakRef(ac)
353357
const abort = function () {
354-
acRef.deref()?.abort(this.reason)
358+
ac.abort(this.reason)
355359
}
356360

357-
if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) {
358-
setMaxListeners(100, signal)
359-
}
361+
// Third-party AbortControllers may not work with these.
362+
// See https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619
363+
try {
364+
if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) {
365+
setMaxListeners(100, signal)
366+
}
367+
} catch {}
360368

361369
signal.addEventListener('abort', abort, { once: true })
362370
requestFinalizer.register(this, { signal, abort })

0 commit comments

Comments
 (0)