undici 7.24.6 → 7.24.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/docs/api/Dispatcher.md +4 -4
- package/docs/docs/api/RedirectHandler.md +1 -4
- package/lib/web/fetch/index.js +33 -4
- package/lib/web/fetch/util.js +4 -2
- package/package.json +1 -1
- package/types/dispatcher.d.ts +0 -6
- package/types/fetch.d.ts +24 -4
- package/types/formdata.d.ts +6 -0
- package/types/handlers.d.ts +1 -2
|
@@ -364,7 +364,7 @@ client.dispatch({
|
|
|
364
364
|
|
|
365
365
|
### `Dispatcher.pipeline(options, handler)`
|
|
366
366
|
|
|
367
|
-
For easy use with [stream.pipeline](https://nodejs.org/api/stream.html#
|
|
367
|
+
For easy use with [stream.pipeline](https://nodejs.org/api/stream.html#streampipelinesource-transforms-destination-options). The `handler` argument should return a `Readable` from which the result will be read. Usually it should just return the `body` argument unless some kind of transformation needs to be performed based on e.g. `headers` or `statusCode`. The `handler` should validate the response and save any required state. If there is an error, it should be thrown. The function returns a `Duplex` which writes to the request and reads from the response.
|
|
368
368
|
|
|
369
369
|
Arguments:
|
|
370
370
|
|
|
@@ -963,7 +963,7 @@ const { Client, interceptors } = require("undici");
|
|
|
963
963
|
const { redirect } = interceptors;
|
|
964
964
|
|
|
965
965
|
const client = new Client("http://service.example").compose(
|
|
966
|
-
redirect({ maxRedirections: 3,
|
|
966
|
+
redirect({ maxRedirections: 3, throwOnMaxRedirect: true })
|
|
967
967
|
);
|
|
968
968
|
client.request({ path: "/" })
|
|
969
969
|
```
|
|
@@ -1036,10 +1036,10 @@ The `dns` interceptor enables you to cache DNS lookups for a given duration, per
|
|
|
1036
1036
|
- `dualStack` - Whether to resolve both IPv4 and IPv6 addresses. Default: `true`.
|
|
1037
1037
|
- It will also attempt a happy-eyeballs-like approach to connect to the available addresses in case of a connection failure.
|
|
1038
1038
|
- `affinity` - Whether to use IPv4 or IPv6 addresses. Default: `4`.
|
|
1039
|
-
- It can be either `
|
|
1039
|
+
- It can be either `4` or `6`.
|
|
1040
1040
|
- It will only take effect if `dualStack` is `false`.
|
|
1041
1041
|
- `lookup: (hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException | null, addresses: DNSInterceptorRecord[]) => void) => void` - Custom lookup function. Default: `dns.lookup`.
|
|
1042
|
-
- For more info see [dns.lookup](https://nodejs.org/api/dns.html#
|
|
1042
|
+
- For more info see [dns.lookup](https://nodejs.org/api/dns.html#dnslookuphostname-options-callback).
|
|
1043
1043
|
- `pick: (origin: URL, records: DNSInterceptorRecords, affinity: 4 | 6) => DNSInterceptorRecord` - Custom pick function. Default: `RoundRobin`.
|
|
1044
1044
|
- The function should return a single record from the records array.
|
|
1045
1045
|
- By default a simplified version of Round Robin is used.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A class that handles redirection logic for HTTP requests.
|
|
4
4
|
|
|
5
|
-
## `new RedirectHandler(dispatch, maxRedirections, opts, handler
|
|
5
|
+
## `new RedirectHandler(dispatch, maxRedirections, opts, handler)`
|
|
6
6
|
|
|
7
7
|
Arguments:
|
|
8
8
|
|
|
@@ -10,7 +10,6 @@ Arguments:
|
|
|
10
10
|
- **maxRedirections** `number` - Maximum number of redirections allowed.
|
|
11
11
|
- **opts** `object` - Options for handling redirection.
|
|
12
12
|
- **handler** `object` - An object containing handlers for different stages of the request lifecycle.
|
|
13
|
-
- **redirectionLimitReached** `boolean` (default: `false`) - A flag that the implementer can provide to enable or disable the feature. If set to `false`, it indicates that the caller doesn't want to use the feature and prefers the old behavior.
|
|
14
13
|
|
|
15
14
|
Returns: `RedirectHandler`
|
|
16
15
|
|
|
@@ -20,7 +19,6 @@ Returns: `RedirectHandler`
|
|
|
20
19
|
- **maxRedirections** `number` (required) - Maximum number of redirections allowed.
|
|
21
20
|
- **opts** `object` (required) - Options for handling redirection.
|
|
22
21
|
- **handler** `object` (required) - Handlers for different stages of the request lifecycle.
|
|
23
|
-
- **redirectionLimitReached** `boolean` (default: `false`) - A flag that the implementer can provide to enable or disable the feature. If set to `false`, it indicates that the caller doesn't want to use the feature and prefers the old behavior.
|
|
24
22
|
|
|
25
23
|
### Properties
|
|
26
24
|
|
|
@@ -30,7 +28,6 @@ Returns: `RedirectHandler`
|
|
|
30
28
|
- **maxRedirections** `number` - Maximum number of redirections allowed.
|
|
31
29
|
- **handler** `object` - Handlers for different stages of the request lifecycle.
|
|
32
30
|
- **history** `Array` - An array representing the history of URLs during redirection.
|
|
33
|
-
- **redirectionLimitReached** `boolean` - Indicates whether the redirection limit has been reached.
|
|
34
31
|
|
|
35
32
|
### Methods
|
|
36
33
|
|
package/lib/web/fetch/index.js
CHANGED
|
@@ -1644,12 +1644,25 @@ async function httpNetworkOrCacheFetch (
|
|
|
1644
1644
|
// 14. If response’s status is 401, httpRequest’s response tainting is not "cors",
|
|
1645
1645
|
// includeCredentials is true, and request’s traversable for user prompts is
|
|
1646
1646
|
// a traversable navigable:
|
|
1647
|
-
|
|
1647
|
+
//
|
|
1648
|
+
// In Node.js there is no traversable navigable to prompt the user, but we
|
|
1649
|
+
// still need to handle URL-embedded credentials so authentication retries
|
|
1650
|
+
// for WebSocket handshakes continue to work.
|
|
1651
|
+
if (response.status === 401 && httpRequest.responseTainting !== 'cors' && includeCredentials && (
|
|
1652
|
+
request.useURLCredentials !== undefined ||
|
|
1653
|
+
isTraversableNavigable(request.traversableForUserPrompts)
|
|
1654
|
+
)) {
|
|
1648
1655
|
// 2. If request’s body is non-null, then:
|
|
1649
1656
|
if (request.body != null) {
|
|
1650
1657
|
// 1. If request’s body’s source is null, then return a network error.
|
|
1651
1658
|
if (request.body.source == null) {
|
|
1652
|
-
|
|
1659
|
+
// Note: In Node.js, this code path should not be reached because
|
|
1660
|
+
// isTraversableNavigable() returns false for non-navigable contexts.
|
|
1661
|
+
// However, we handle it gracefully by returning the response instead of
|
|
1662
|
+
// a network error, as we won't actually retry the request.
|
|
1663
|
+
// This aligns with the Fetch spec discussion in whatwg/fetch#1132,
|
|
1664
|
+
// which allows implementations flexibility when credentials can't be obtained.
|
|
1665
|
+
return response
|
|
1653
1666
|
}
|
|
1654
1667
|
|
|
1655
1668
|
// 2. Set request’s body to the body of the result of safely extracting
|
|
@@ -2187,7 +2200,15 @@ async function httpNetworkFetch (
|
|
|
2187
2200
|
const headersList = new HeadersList()
|
|
2188
2201
|
|
|
2189
2202
|
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
2190
|
-
|
|
2203
|
+
const nameStr = bufferToLowerCasedHeaderName(rawHeaders[i])
|
|
2204
|
+
const value = rawHeaders[i + 1]
|
|
2205
|
+
if (Array.isArray(value) && !Buffer.isBuffer(rawHeaders[i + 1])) {
|
|
2206
|
+
for (const val of value) {
|
|
2207
|
+
headersList.append(nameStr, val.toString('latin1'), true)
|
|
2208
|
+
}
|
|
2209
|
+
} else {
|
|
2210
|
+
headersList.append(nameStr, value.toString('latin1'), true)
|
|
2211
|
+
}
|
|
2191
2212
|
}
|
|
2192
2213
|
const location = headersList.get('location', true)
|
|
2193
2214
|
|
|
@@ -2356,7 +2377,15 @@ async function httpNetworkFetch (
|
|
|
2356
2377
|
const headersList = new HeadersList()
|
|
2357
2378
|
|
|
2358
2379
|
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
2359
|
-
|
|
2380
|
+
const nameStr = bufferToLowerCasedHeaderName(rawHeaders[i])
|
|
2381
|
+
const value = rawHeaders[i + 1]
|
|
2382
|
+
if (Array.isArray(value) && !Buffer.isBuffer(rawHeaders[i + 1])) {
|
|
2383
|
+
for (const val of value) {
|
|
2384
|
+
headersList.append(nameStr, val.toString('latin1'), true)
|
|
2385
|
+
}
|
|
2386
|
+
} else {
|
|
2387
|
+
headersList.append(nameStr, value.toString('latin1'), true)
|
|
2388
|
+
}
|
|
2360
2389
|
}
|
|
2361
2390
|
|
|
2362
2391
|
resolve({
|
package/lib/web/fetch/util.js
CHANGED
|
@@ -1447,8 +1447,10 @@ function includesCredentials (url) {
|
|
|
1447
1447
|
* @param {object|string} navigable
|
|
1448
1448
|
*/
|
|
1449
1449
|
function isTraversableNavigable (navigable) {
|
|
1450
|
-
//
|
|
1451
|
-
|
|
1450
|
+
// Returns true only if we have an actual traversable navigable object
|
|
1451
|
+
// that can prompt the user for credentials. In Node.js, this will always
|
|
1452
|
+
// be false since there's no Window object or navigable.
|
|
1453
|
+
return navigable != null && navigable !== 'client' && navigable !== 'no-traversable'
|
|
1452
1454
|
}
|
|
1453
1455
|
|
|
1454
1456
|
class EnvironmentSettingsObjectBase {
|
package/package.json
CHANGED
package/types/dispatcher.d.ts
CHANGED
|
@@ -137,8 +137,6 @@ declare namespace Dispatcher {
|
|
|
137
137
|
signal?: AbortSignal | EventEmitter | null;
|
|
138
138
|
/** This argument parameter is passed through to `ConnectData` */
|
|
139
139
|
opaque?: TOpaque;
|
|
140
|
-
/** Default: false */
|
|
141
|
-
redirectionLimitReached?: boolean;
|
|
142
140
|
/** Default: `null` */
|
|
143
141
|
responseHeaders?: 'raw' | null;
|
|
144
142
|
}
|
|
@@ -147,8 +145,6 @@ declare namespace Dispatcher {
|
|
|
147
145
|
opaque?: TOpaque;
|
|
148
146
|
/** Default: `null` */
|
|
149
147
|
signal?: AbortSignal | EventEmitter | null;
|
|
150
|
-
/** Default: false */
|
|
151
|
-
redirectionLimitReached?: boolean;
|
|
152
148
|
/** Default: `null` */
|
|
153
149
|
onInfo?: (info: { statusCode: number, headers: Record<string, string | string[]> }) => void;
|
|
154
150
|
/** Default: `null` */
|
|
@@ -170,8 +166,6 @@ declare namespace Dispatcher {
|
|
|
170
166
|
protocol?: string;
|
|
171
167
|
/** Default: `null` */
|
|
172
168
|
signal?: AbortSignal | EventEmitter | null;
|
|
173
|
-
/** Default: false */
|
|
174
|
-
redirectionLimitReached?: boolean;
|
|
175
169
|
/** Default: `null` */
|
|
176
170
|
responseHeaders?: 'raw' | null;
|
|
177
171
|
}
|
package/types/fetch.d.ts
CHANGED
|
@@ -60,12 +60,32 @@ export interface SpecIterator<T, TReturn = any, TNext = undefined> {
|
|
|
60
60
|
next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
export interface
|
|
63
|
+
export interface SpecIteratorObject<T, TReturn = undefined, TNext = unknown> extends SpecIterator<T, TReturn, TNext> {
|
|
64
|
+
[Symbol.iterator](): SpecIteratorObject<T, TReturn, TNext>;
|
|
65
|
+
map<U>(callbackfn: (value: T, index: number) => U): SpecIteratorObject<U>;
|
|
66
|
+
filter<S extends T>(predicate: (value: T, index: number) => value is S): SpecIteratorObject<S>;
|
|
67
|
+
filter(predicate: (value: T, index: number) => unknown): SpecIteratorObject<T>;
|
|
68
|
+
take(limit: number): SpecIteratorObject<T>;
|
|
69
|
+
drop(count: number): SpecIteratorObject<T>;
|
|
70
|
+
flatMap<U>(callbackfn: (value: T, index: number) => Iterator<U> | Iterable<U>): SpecIteratorObject<U>;
|
|
71
|
+
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number) => T): T;
|
|
72
|
+
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number) => T, initialValue: T): T;
|
|
73
|
+
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U): U;
|
|
74
|
+
toArray(): T[];
|
|
75
|
+
forEach(callbackfn: (value: T, index: number) => void): void;
|
|
76
|
+
some(predicate: (value: T, index: number) => unknown): boolean;
|
|
77
|
+
every(predicate: (value: T, index: number) => unknown): boolean;
|
|
78
|
+
find<S extends T>(predicate: (value: T, index: number) => value is S): S | undefined;
|
|
79
|
+
find(predicate: (value: T, index: number) => unknown): T | undefined;
|
|
80
|
+
readonly [Symbol.toStringTag]: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface SpecIterableIterator<T> extends SpecIteratorObject<T> {
|
|
64
84
|
[Symbol.iterator](): SpecIterableIterator<T>;
|
|
65
85
|
}
|
|
66
86
|
|
|
67
87
|
export interface SpecIterable<T> {
|
|
68
|
-
[Symbol.iterator]():
|
|
88
|
+
[Symbol.iterator](): SpecIterableIterator<T>;
|
|
69
89
|
}
|
|
70
90
|
|
|
71
91
|
export type HeadersInit = [string, string][] | HeaderRecord | Headers
|
|
@@ -173,7 +193,7 @@ export declare class Request extends BodyMixin {
|
|
|
173
193
|
readonly signal: AbortSignal
|
|
174
194
|
readonly duplex: RequestDuplex
|
|
175
195
|
|
|
176
|
-
|
|
196
|
+
public clone (): Request
|
|
177
197
|
}
|
|
178
198
|
|
|
179
199
|
export interface ResponseInit {
|
|
@@ -203,7 +223,7 @@ export declare class Response extends BodyMixin {
|
|
|
203
223
|
readonly url: string
|
|
204
224
|
readonly redirected: boolean
|
|
205
225
|
|
|
206
|
-
|
|
226
|
+
public clone (): Response
|
|
207
227
|
|
|
208
228
|
static error (): Response
|
|
209
229
|
static json (data: any, init?: ResponseInit): Response
|
package/types/formdata.d.ts
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
import { File } from 'node:buffer'
|
|
5
5
|
import { SpecIterableIterator } from './fetch'
|
|
6
6
|
|
|
7
|
+
declare module 'node:buffer' {
|
|
8
|
+
interface File {
|
|
9
|
+
readonly [Symbol.toStringTag]: string
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
/**
|
|
8
14
|
* A `string` or `File` that represents a single value from a set of `FormData` key-value pairs.
|
|
9
15
|
*/
|
package/types/handlers.d.ts
CHANGED
|
@@ -5,8 +5,7 @@ export declare class RedirectHandler implements Dispatcher.DispatchHandler {
|
|
|
5
5
|
dispatch: Dispatcher.Dispatch,
|
|
6
6
|
maxRedirections: number,
|
|
7
7
|
opts: Dispatcher.DispatchOptions,
|
|
8
|
-
handler: Dispatcher.DispatchHandler
|
|
9
|
-
redirectionLimitReached: boolean
|
|
8
|
+
handler: Dispatcher.DispatchHandler
|
|
10
9
|
)
|
|
11
10
|
}
|
|
12
11
|
|