Skip to content

Commit 87b248e

Browse files
nodejs-github-botbengl
authored andcommitted
deps: update undici to 5.3.0
PR-URL: #43197 Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent d6cf409 commit 87b248e

22 files changed

+487
-284
lines changed

deps/undici/src/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ You can pass an optional dispatcher to `fetch` as:
198198

199199
```js
200200
import { fetch, Agent } from 'undici'
201-
201+
202202
const res = await fetch('https://example.com', {
203203
// Mocks are also supported
204204
dispatcher: new Agent({
@@ -375,6 +375,7 @@ Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling
375375
* [__Daniele Belardi__](https://github.com/dnlup), <https://www.npmjs.com/~dnlup>
376376
* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood>
377377
* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>
378+
* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>
378379
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
379380
* [__Szymon Marczak__](https://github.com/szmarczak), <https://www.npmjs.com/~szmarczak>
380381
* [__Tomas Della Vedova__](https://github.com/delvedor), <https://www.npmjs.com/~delvedor>

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,20 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
194194
* **method** `string`
195195
* **body** `string | Buffer | Uint8Array | stream.Readable | Iterable | AsyncIterable | null` (optional) - Default: `null`
196196
* **headers** `UndiciHeaders | string[]` (optional) - Default: `null`.
197+
* **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.
197198
* **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.
198199
* **blocking** `boolean` (optional) - Default: `false` - 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.
199200
* **upgrade** `string | null` (optional) - Default: `null` - Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`.
200201
* **bodyTimeout** `number | null` (optional) - 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 30 seconds.
201202
* **headersTimeout** `number | null` (optional) - The amount of time the parser will wait to receive the complete HTTP headers. Defaults to 30 seconds.
203+
* **throwOnError** `boolean` (optional) - Default: `false` - Whether Undici should throw an error upon receiving a 4xx or 5xx response from the server.
202204

203205
#### Parameter: `DispatchHandler`
204206

205207
* **onConnect** `(abort: () => void, context: object) => void` - Invoked before request is dispatched on socket. May be invoked multiple times when a request is retried when the request at the head of the pipeline fails.
206208
* **onError** `(error: Error) => void` - Invoked when an error has occurred. May not throw.
207209
* **onUpgrade** `(statusCode: number, headers: Buffer[], socket: Duplex) => void` (optional) - Invoked when request is upgraded. Required if `DispatchOptions.upgrade` is defined or `DispatchOptions.method === 'CONNECT'`.
208-
* **onHeaders** `(statusCode: number, headers: Buffer[], resume: () => void) => boolean` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests.
210+
* **onHeaders** `(statusCode: number, headers: Buffer[], resume: () => void, statusText: string) => boolean` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests.
209211
* **onData** `(chunk: Buffer) => boolean` - Invoked when response payload data is received. Not required for `upgrade` requests.
210212
* **onComplete** `(trailers: Buffer[]) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests.
211213
* **onBodySent** `(chunk: string | Buffer | Uint8Array) => void` - Invoked when a body chunk is sent to the server. Not required. For a stream or iterable body this will be invoked for every chunk. For other body types, it will be invoked once after the body is sent.

deps/undici/src/docs/best-practices/mocking-request.md

+32
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,36 @@ const badRequest = await bankTransfer('1234567890', '100')
101101
// subsequent request to origin http://localhost:3000 was not allowed (net.connect disabled)
102102
```
103103

104+
## Reply with data based on request
104105

106+
If the mocked response needs to be dynamically derived from the request parameters, you can provide a function instead of an object to `reply`
107+
108+
```js
109+
mockPool.intercept({
110+
path: '/bank-transfer',
111+
method: 'POST',
112+
headers: {
113+
'X-TOKEN-SECRET': 'SuperSecretToken',
114+
},
115+
body: JSON.stringify({
116+
recepient: '1234567890',
117+
amount: '100'
118+
})
119+
}).reply(200, (opts) => {
120+
// do something with opts
121+
122+
return { message: 'transaction processed' }
123+
})
124+
```
125+
126+
in this case opts will be
127+
128+
```
129+
{
130+
method: 'POST',
131+
headers: { 'X-TOKEN-SECRET': 'SuperSecretToken' },
132+
body: '{"recepient":"1234567890","amount":"100"}',
133+
origin: 'http://localhost:3000',
134+
path: '/bank-transfer'
135+
}
136+
```

deps/undici/src/index.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { request, pipeline, stream, connect, upgrade } from './types/api'
1616
export * from './types/fetch'
1717
export * from './types/file'
1818
export * from './types/formdata'
19+
export * from './types/diagnostics-channel'
1920
export { Interceptable } from './types/mock-interceptor'
2021

2122
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent }

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

+12-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
const Readable = require('./readable')
44
const {
55
InvalidArgumentError,
6-
RequestAbortedError
6+
RequestAbortedError,
7+
ResponseStatusCodeError
78
} = require('../core/errors')
89
const util = require('../core/util')
910
const { AsyncResource } = require('async_hooks')
@@ -15,7 +16,7 @@ class RequestHandler extends AsyncResource {
1516
throw new InvalidArgumentError('invalid opts')
1617
}
1718

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

2021
try {
2122
if (typeof callback !== 'function') {
@@ -51,6 +52,7 @@ class RequestHandler extends AsyncResource {
5152
this.trailers = {}
5253
this.context = null
5354
this.onInfo = onInfo || null
55+
this.throwOnError = throwOnError
5456

5557
if (util.isStream(body)) {
5658
body.on('error', (err) => {
@@ -70,7 +72,7 @@ class RequestHandler extends AsyncResource {
7072
this.context = context
7173
}
7274

73-
onHeaders (statusCode, rawHeaders, resume) {
75+
onHeaders (statusCode, rawHeaders, resume, statusMessage) {
7476
const { callback, opaque, abort, context } = this
7577

7678
if (statusCode < 200) {
@@ -89,6 +91,13 @@ class RequestHandler extends AsyncResource {
8991
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
9092

9193
if (callback !== null) {
94+
if (this.throwOnError && statusCode >= 400) {
95+
this.runInAsyncScope(callback, null,
96+
new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)
97+
)
98+
return
99+
}
100+
92101
this.runInAsyncScope(callback, null, null, {
93102
statusCode,
94103
headers,

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

+14
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@ class BodyTimeoutError extends UndiciError {
5656
}
5757
}
5858

59+
class ResponseStatusCodeError extends UndiciError {
60+
constructor (message, statusCode, headers) {
61+
super(message)
62+
Error.captureStackTrace(this, ResponseStatusCodeError)
63+
this.name = 'ResponseStatusCodeError'
64+
this.message = message || 'Response Status Code Error'
65+
this.code = 'UND_ERR_RESPONSE_STATUS_CODE'
66+
this.status = statusCode
67+
this.statusCode = statusCode
68+
this.headers = headers
69+
}
70+
}
71+
5972
class InvalidArgumentError extends UndiciError {
6073
constructor (message) {
6174
super(message)
@@ -186,6 +199,7 @@ module.exports = {
186199
BodyTimeoutError,
187200
RequestContentLengthMismatchError,
188201
ConnectTimeoutError,
202+
ResponseStatusCodeError,
189203
InvalidArgumentError,
190204
InvalidReturnValueError,
191205
RequestAbortedError,

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const {
44
InvalidArgumentError,
55
NotSupportedError
66
} = require('./errors')
7-
const util = require('./util')
87
const assert = require('assert')
8+
const util = require('./util')
99

1010
const kHandler = Symbol('handler')
1111

@@ -38,11 +38,13 @@ class Request {
3838
method,
3939
body,
4040
headers,
41+
query,
4142
idempotent,
4243
blocking,
4344
upgrade,
4445
headersTimeout,
45-
bodyTimeout
46+
bodyTimeout,
47+
throwOnError
4648
}, handler) {
4749
if (typeof path !== 'string') {
4850
throw new InvalidArgumentError('path must be a string')
@@ -70,6 +72,8 @@ class Request {
7072

7173
this.bodyTimeout = bodyTimeout
7274

75+
this.throwOnError = throwOnError === true
76+
7377
this.method = method
7478

7579
if (body == null) {
@@ -97,7 +101,7 @@ class Request {
97101

98102
this.upgrade = upgrade || null
99103

100-
this.path = path
104+
this.path = query ? util.buildURL(path, query) : path
101105

102106
this.origin = origin
103107

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

+47-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,51 @@ function isBlobLike (object) {
2626
)
2727
}
2828

29+
function isObject (val) {
30+
return val !== null && typeof val === 'object'
31+
}
32+
33+
// this escapes all non-uri friendly characters
34+
function encode (val) {
35+
return encodeURIComponent(val)
36+
}
37+
38+
// based on https://github.com/axios/axios/blob/63e559fa609c40a0a460ae5d5a18c3470ffc6c9e/lib/helpers/buildURL.js (MIT license)
39+
function buildURL (url, queryParams) {
40+
if (url.includes('?') || url.includes('#')) {
41+
throw new Error('Query params cannot be passed when url already contains "?" or "#".')
42+
}
43+
if (!isObject(queryParams)) {
44+
throw new Error('Query params must be an object')
45+
}
46+
47+
const parts = []
48+
for (let [key, val] of Object.entries(queryParams)) {
49+
if (val === null || typeof val === 'undefined') {
50+
continue
51+
}
52+
53+
if (!Array.isArray(val)) {
54+
val = [val]
55+
}
56+
57+
for (const v of val) {
58+
if (isObject(v)) {
59+
throw new Error('Passing object as a query param is not supported, please serialize to string up-front')
60+
}
61+
parts.push(encode(key) + '=' + encode(v))
62+
}
63+
}
64+
65+
const serializedParams = parts.join('&')
66+
67+
if (serializedParams) {
68+
url += '?' + serializedParams
69+
}
70+
71+
return url
72+
}
73+
2974
function parseURL (url) {
3075
if (typeof url === 'string') {
3176
url = new URL(url)
@@ -357,5 +402,6 @@ module.exports = {
357402
isBuffer,
358403
validateHandler,
359404
getSocketInfo,
360-
isFormDataLike
405+
isFormDataLike,
406+
buildURL
361407
}

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

-8
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,6 @@ class File extends Blob {
6969
}
7070

7171
get [Symbol.toStringTag] () {
72-
if (!(this instanceof File)) {
73-
throw new TypeError('Illegal invocation')
74-
}
75-
7672
return this.constructor.name
7773
}
7874
}
@@ -190,10 +186,6 @@ class FileLike {
190186
}
191187

192188
get [Symbol.toStringTag] () {
193-
if (!(this instanceof FileLike)) {
194-
throw new TypeError('Illegal invocation')
195-
}
196-
197189
return 'File'
198190
}
199191
}

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

+3-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const { File, FileLike } = require('./file')
66
const { Blob } = require('buffer')
77

88
class FormData {
9+
static name = 'FormData'
10+
911
constructor (...args) {
1012
if (args.length > 0 && !(args[0]?.constructor?.name === 'HTMLFormElement')) {
1113
throw new TypeError(
@@ -182,10 +184,6 @@ class FormData {
182184
}
183185

184186
get [Symbol.toStringTag] () {
185-
if (!(this instanceof FormData)) {
186-
throw new TypeError('Illegal invocation')
187-
}
188-
189187
return this.constructor.name
190188
}
191189

@@ -269,4 +267,4 @@ function makeEntry (name, value, filename) {
269267
return entry
270268
}
271269

272-
module.exports = { FormData: globalThis.FormData ?? FormData }
270+
module.exports = { FormData }

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

+3-15
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ const {
3131
coarsenedSharedCurrentTime,
3232
createDeferredPromise,
3333
isBlobLike,
34-
CORBCheck,
3534
sameOrigin,
3635
isCancelled,
3736
isAborted
@@ -52,7 +51,6 @@ const EE = require('events')
5251
const { Readable, pipeline } = require('stream')
5352
const { isErrored, isReadable } = require('../core/util')
5453
const { dataURLProcessor } = require('./dataURL')
55-
const { kIsMockActive } = require('../mock/mock-symbols')
5654
const { TransformStream } = require('stream/web')
5755

5856
/** @type {import('buffer').resolveObjectURL} */
@@ -588,18 +586,8 @@ async function mainFetch (fetchParams, recursive = false) {
588586
// 2. Set request’s response tainting to "opaque".
589587
request.responseTainting = 'opaque'
590588

591-
// 3. Let noCorsResponse be the result of running scheme fetch given
592-
// fetchParams.
593-
const noCorsResponse = await schemeFetch(fetchParams)
594-
595-
// 4. If noCorsResponse is a filtered response or the CORB check with
596-
// request and noCorsResponse returns allowed, then return noCorsResponse.
597-
if (noCorsResponse.status === 0 || CORBCheck(request, noCorsResponse) === 'allowed') {
598-
return noCorsResponse
599-
}
600-
601-
// 5. Return a new response whose status is noCorsResponse’s status.
602-
return makeResponse({ status: noCorsResponse.status })
589+
// 3. Return the result of running scheme fetch given fetchParams.
590+
return await schemeFetch(fetchParams)
603591
}
604592

605593
// request’s current URL’s scheme is not an HTTP(S) scheme
@@ -1923,7 +1911,7 @@ async function httpNetworkFetch (
19231911
path: url.pathname + url.search,
19241912
origin: url.origin,
19251913
method: request.method,
1926-
body: fetchParams.controller.dispatcher[kIsMockActive] ? request.body && request.body.source : body,
1914+
body: fetchParams.controller.dispatcher.isMockActive ? request.body && request.body.source : body,
19271915
headers: [...request.headersList].flat(),
19281916
maxRedirections: 0,
19291917
bodyTimeout: 300_000,

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

-4
Original file line numberDiff line numberDiff line change
@@ -516,10 +516,6 @@ class Request {
516516
}
517517

518518
get [Symbol.toStringTag] () {
519-
if (!(this instanceof Request)) {
520-
throw new TypeError('Illegal invocation')
521-
}
522-
523519
return this.constructor.name
524520
}
525521

0 commit comments

Comments
 (0)