undici 4.9.4 → 4.10.2

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/README.md CHANGED
@@ -93,7 +93,7 @@ Arguments:
93
93
 
94
94
  * **url** `string | URL | UrlObject`
95
95
  * **options** [`RequestOptions`](./docs/api/Dispatcher.md#parameter-requestoptions)
96
- * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
96
+ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
97
97
  * **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
98
98
  * **maxRedirections** `Integer` - Default: `0`
99
99
 
@@ -109,7 +109,7 @@ Arguments:
109
109
 
110
110
  * **url** `string | URL | UrlObject`
111
111
  * **options** [`StreamOptions`](./docs/api/Dispatcher.md#parameter-streamoptions)
112
- * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
112
+ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
113
113
  * **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
114
114
  * **maxRedirections** `Integer` - Default: `0`
115
115
  * **factory** `Dispatcher.stream.factory`
@@ -118,7 +118,7 @@ Returns a promise with the result of the `Dispatcher.stream` method.
118
118
 
119
119
  Calls `options.dispatcher.stream(options, factory)`.
120
120
 
121
- See [Dispatcher.stream](docs/api/Dispatcher.md#dispatcherstream) for more details.
121
+ See [Dispatcher.stream](docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback) for more details.
122
122
 
123
123
  ### `undici.pipeline([url, options, ]handler): Duplex`
124
124
 
@@ -126,7 +126,7 @@ Arguments:
126
126
 
127
127
  * **url** `string | URL | UrlObject`
128
128
  * **options** [`PipelineOptions`](docs/api/Dispatcher.md#parameter-pipelineoptions)
129
- * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
129
+ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
130
130
  * **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
131
131
  * **maxRedirections** `Integer` - Default: `0`
132
132
  * **handler** `Dispatcher.pipeline.handler`
@@ -135,7 +135,7 @@ Returns: `stream.Duplex`
135
135
 
136
136
  Calls `options.dispatch.pipeline(options, handler)`.
137
137
 
138
- See [Dispatcher.pipeline](docs/api/Dispatcher.md#dispatcherpipeline) for more details.
138
+ See [Dispatcher.pipeline](docs/api/Dispatcher.md#dispatcherpipelineoptions-handler) for more details.
139
139
 
140
140
  ### `undici.connect([url, options]): Promise`
141
141
 
@@ -145,7 +145,7 @@ Arguments:
145
145
 
146
146
  * **url** `string | URL | UrlObject`
147
147
  * **options** [`ConnectOptions`](docs/api/Dispatcher.md#parameter-connectoptions)
148
- * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
148
+ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
149
149
  * **maxRedirections** `Integer` - Default: `0`
150
150
  * **callback** `(err: Error | null, data: ConnectData | null) => void` (optional)
151
151
 
@@ -153,7 +153,7 @@ Returns a promise with the result of the `Dispatcher.connect` method.
153
153
 
154
154
  Calls `options.dispatch.connect(options)`.
155
155
 
156
- See [Dispatcher.connect](docs/api/Dispatcher.md#dispatcherconnect) for more details.
156
+ See [Dispatcher.connect](docs/api/Dispatcher.md#dispatcherconnectoptions-callback) for more details.
157
157
 
158
158
  ### `undici.fetch(input[, init]): Promise`
159
159
 
@@ -162,7 +162,7 @@ Implements [fetch](https://fetch.spec.whatwg.org/#fetch-method).
162
162
  * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
163
163
  * https://fetch.spec.whatwg.org/#fetch-method
164
164
 
165
- Only supported on Node 16+.
165
+ Only supported on Node 16.5+.
166
166
 
167
167
  This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant with the Fetch Standard. We plan to ship breaking changes to this feature until it is out of experimental.
168
168
 
@@ -170,7 +170,7 @@ Basic usage example:
170
170
 
171
171
  ```js
172
172
  import {fetch} from 'undici';
173
-
173
+
174
174
  async function fetchJson() {
175
175
  const res = await fetch('https://example.com')
176
176
  const json = await res.json()
@@ -180,7 +180,7 @@ Basic usage example:
180
180
 
181
181
  #### `response.body`
182
182
 
183
- Nodejs has two kinds of streams: [web streams](https://nodejs.org/dist/latest-v16.x/docs/api/webstreams.html) which follow the API of the WHATWG web standard found in browsers, and an older Node-specific [streams API](https://nodejs.org/api/stream.html). `response.body` returns a readable web stream. If you would prefer to work with a Node stream you can convert a web stream using `.fromWeb()`.
183
+ Nodejs has two kinds of streams: [web streams](https://nodejs.org/dist/latest-v16.x/docs/api/webstreams.html) which follow the API of the WHATWG web standard found in browsers, and an older Node-specific [streams API](https://nodejs.org/api/stream.html). `response.body` returns a readable web stream. If you would prefer to work with a Node stream you can convert a web stream using `.fromWeb()`.
184
184
 
185
185
  ```js
186
186
  import {fetch} from 'undici';
@@ -208,7 +208,7 @@ garbage collection in Node is less aggressive and deterministic (due to the lack
208
208
  of clear idle periods that browser have through the rendering refresh rate)
209
209
  which means that leaving the release of connection resources to the garbage collector
210
210
  can lead to excessive connection usage, reduced performance (due to less connection re-use),
211
- and even stalls or deadlocks when running out of connections. Therefore, it is highly
211
+ and even stalls or deadlocks when running out of connections. Therefore, it is highly
212
212
  recommended to always either consume or cancel the response body.
213
213
 
214
214
  ```js
@@ -234,7 +234,7 @@ Arguments:
234
234
 
235
235
  * **url** `string | URL | UrlObject`
236
236
  * **options** [`UpgradeOptions`](docs/api/Dispatcher.md#parameter-upgradeoptions)
237
- * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
237
+ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
238
238
  * **maxRedirections** `Integer` - Default: `0`
239
239
  * **callback** `(error: Error | null, data: UpgradeData) => void` (optional)
240
240
 
package/docs/api/Agent.md CHANGED
@@ -16,64 +16,64 @@ Returns: `Agent`
16
16
 
17
17
  ### Parameter: `AgentOptions`
18
18
 
19
- Extends: [`ClientOptions`](docs/api/Pool.md#parameter-pooloptions)
19
+ Extends: [`ClientOptions`](Pool.md#parameter-pooloptions)
20
20
 
21
- * **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Pool(origin, opts)`
21
+ * **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Pool(origin, opts)`
22
22
  * **maxRedirections** `Integer` - Default: `0`. The number of HTTP redirection to follow unless otherwise specified in `DispatchOptions`.
23
23
 
24
24
  ## Instance Properties
25
25
 
26
26
  ### `Agent.closed`
27
27
 
28
- Implements [Client.closed](docs/api/Client.md#clientclosed)
28
+ Implements [Client.closed](Client.md#clientclosed)
29
29
 
30
30
  ### `Agent.destroyed`
31
31
 
32
- Implements [Client.destroyed](docs/api/Client.md#clientdestroyed)
32
+ Implements [Client.destroyed](Client.md#clientdestroyed)
33
33
 
34
34
  ## Instance Methods
35
35
 
36
36
  ### `Agent.close([callback])`
37
37
 
38
- Implements [`Dispatcher.close([callback])`](docs/api/Dispatcher.md#clientclose-callback-).
38
+ Implements [`Dispatcher.close([callback])`](Dispatcher.md#dispatcherclosecallback-promise).
39
39
 
40
40
  ### `Agent.destroy([error, callback])`
41
41
 
42
- Implements [`Dispatcher.destroy([error, callback])`](docs/api/Dispatcher.md#dispatcher-callback-).
42
+ Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
43
43
 
44
- ### `Agent.dispatch(options, handlers: AgentDispatchOptions)`
44
+ ### `Agent.dispatch(options, handler: AgentDispatchOptions)`
45
45
 
46
- Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
46
+ Implements [`Dispatcher.dispatch(options, handler)`](Dispatcher.md#dispatcherdispatchoptions-handler).
47
47
 
48
48
  #### Parameter: `AgentDispatchOptions`
49
49
 
50
- Extends: [`DispatchOptions``](docs/api/Dispatcher.md#parameter-dispatchoptions)
50
+ Extends: [`DispatchOptions`](Dispatcher.md#parameter-dispatchoptions)
51
51
 
52
52
  * **origin** `string | URL`
53
53
  * **maxRedirections** `Integer`.
54
54
 
55
- Implements [`Dispatcher.destroy([error, callback])`](docs/api/Dispatcher.md#dispatcher-callback-).
55
+ Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
56
56
 
57
57
  ### `Agent.connect(options[, callback])`
58
58
 
59
- See [`Dispatcher.connect(options[, callback])`](docs/api/Dispatcher.md#clientconnectoptions--callback).
59
+ See [`Dispatcher.connect(options[, callback])`](Dispatcher.md#dispatcherconnectoptions-callback).
60
60
 
61
- ### `Agent.dispatch(options, handlers)`
61
+ ### `Agent.dispatch(options, handler)`
62
62
 
63
- Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
63
+ Implements [`Dispatcher.dispatch(options, handler)`](Dispatcher.md#dispatcherdispatchoptions-handler).
64
64
 
65
65
  ### `Agent.pipeline(options, handler)`
66
66
 
67
- See [`Dispatcher.pipeline(options, handler)`](docs/api/Dispatcher.md#clientpipelineoptions-handler).
67
+ See [`Dispatcher.pipeline(options, handler)`](Dispatcher.md#dispatcherpipelineoptions-handler).
68
68
 
69
69
  ### `Agent.request(options[, callback])`
70
70
 
71
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
71
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
72
72
 
73
73
  ### `Agent.stream(options, factory[, callback])`
74
74
 
75
- See [`Dispatcher.stream(options, factory[, callback])`](docs/api/Dispatcher.md#clientstreamoptions-factory--callback).
75
+ See [`Dispatcher.stream(options, factory[, callback])`](Dispatcher.md#dispatcherstreamoptions-factory-callback).
76
76
 
77
77
  ### `Agent.upgrade(options[, callback])`
78
78
 
79
- See [`Dispatcher.upgrade(options[, callback])`](docs/api/Dispatcher.md#clientupgradeoptions-callback).
79
+ See [`Dispatcher.upgrade(options[, callback])`](Dispatcher.md#dispatcherupgradeoptions-callback).
@@ -2,7 +2,7 @@
2
2
 
3
3
  Extends: `undici.Dispatcher`
4
4
 
5
- A pool of [Pool](docs/api/Pool.md) instances connected to multiple upstreams.
5
+ A pool of [Pool](Pool.md) instances connected to multiple upstreams.
6
6
 
7
7
  Requests are not guaranteed to be dispatched in order of invocation.
8
8
 
@@ -17,7 +17,7 @@ Arguments:
17
17
 
18
18
  The `PoolOptions` are passed to each of the `Pool` instances being created.
19
19
 
20
- See: [`PoolOptions`](docs/api/Pool.md#parameter-pooloptions)
20
+ See: [`PoolOptions`](Pool.md#parameter-pooloptions)
21
21
 
22
22
  ## Instance Properties
23
23
 
@@ -27,11 +27,11 @@ Returns an array of upstreams that were previously added.
27
27
 
28
28
  ### `BalancedPool.closed`
29
29
 
30
- Implements [Client.closed](docs/api/Client.md#clientclosed)
30
+ Implements [Client.closed](Client.md#clientclosed)
31
31
 
32
32
  ### `BalancedPool.destroyed`
33
33
 
34
- Implements [Client.destroyed](docs/api/Client.md#clientdestroyed)
34
+ Implements [Client.destroyed](Client.md#clientdestroyed)
35
35
 
36
36
  ## Instance Methods
37
37
 
@@ -49,46 +49,46 @@ Removes an upstream that was previously addded.
49
49
 
50
50
  ### `BalancedPool.close([callback])`
51
51
 
52
- Implements [`Dispatcher.close([callback])`](docs/api/Dispatcher.md#clientclose-callback-).
52
+ Implements [`Dispatcher.close([callback])`](Dispatcher.md#dispatcherclosecallback-promise).
53
53
 
54
54
  ### `BalancedPool.destroy([error, callback])`
55
55
 
56
- Implements [`Dispatcher.destroy([error, callback])`](docs/api/Dispatcher.md#dispatcher-callback-).
56
+ Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
57
57
 
58
58
  ### `BalancedPool.connect(options[, callback])`
59
59
 
60
- See [`Dispatcher.connect(options[, callback])`](docs/api/Dispatcher.md#clientconnectoptions--callback).
60
+ See [`Dispatcher.connect(options[, callback])`](Dispatcher.md#dispatcherconnectoptions-callback).
61
61
 
62
62
  ### `BalancedPool.dispatch(options, handlers)`
63
63
 
64
- Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
64
+ Implements [`Dispatcher.dispatch(options, handlers)`](Dispatcher.md#dispatcherdispatchoptions-handler).
65
65
 
66
66
  ### `BalancedPool.pipeline(options, handler)`
67
67
 
68
- See [`Dispatcher.pipeline(options, handler)`](docs/api/Dispatcher.md#clientpipelineoptions-handler).
68
+ See [`Dispatcher.pipeline(options, handler)`](Dispatcher.md#dispatcherpipelineoptions-handler).
69
69
 
70
70
  ### `BalancedPool.request(options[, callback])`
71
71
 
72
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
72
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
73
73
 
74
74
  ### `BalancedPool.stream(options, factory[, callback])`
75
75
 
76
- See [`Dispatcher.stream(options, factory[, callback])`](docs/api/Dispatcher.md#clientstreamoptions-factory--callback).
76
+ See [`Dispatcher.stream(options, factory[, callback])`](Dispatcher.md#dispatcherstreamoptions-factory-callback).
77
77
 
78
78
  ### `BalancedPool.upgrade(options[, callback])`
79
79
 
80
- See [`Dispatcher.upgrade(options[, callback])`](docs/api/Dispatcher.md#clientupgradeoptions-callback).
80
+ See [`Dispatcher.upgrade(options[, callback])`](Dispatcher.md#dispatcherupgradeoptions-callback).
81
81
 
82
82
  ## Instance Events
83
83
 
84
84
  ### Event: `'connect'`
85
85
 
86
- See [Dispatcher Event: `'connect'`](docs/api/Dispatcher.md#event-connect).
86
+ See [Dispatcher Event: `'connect'`](Dispatcher.md#event-connect).
87
87
 
88
88
  ### Event: `'disconnect'`
89
89
 
90
- See [Dispatcher Event: `'disconnect'`](docs/api/Dispatcher.md#event-connect).
90
+ See [Dispatcher Event: `'disconnect'`](Dispatcher.md#event-disconnect).
91
91
 
92
92
  ### Event: `'drain'`
93
93
 
94
- See [Dispatcher Event: `'drain'`](docs/api/Dispatcher.md#event-connect).
94
+ See [Dispatcher Event: `'drain'`](Dispatcher.md#event-drain).
@@ -77,39 +77,37 @@ const client = new Client('https://localhost:3000', {
77
77
 
78
78
  ### `Client.close([callback])`
79
79
 
80
- Implements [`Dispatcher.close([callback])`](docs/api/Dispatcher.md#clientclose-callback-).
80
+ Implements [`Dispatcher.close([callback])`](Dispatcher.md#dispatcherclosecallback-promise).
81
81
 
82
82
  ### `Client.destroy([error, callback])`
83
83
 
84
- Implements [`Dispatcher.destroy([error, callback])`](docs/api/Dispatcher.md#dispatcher-callback-).
84
+ Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
85
85
 
86
86
  Waits until socket is closed before invoking the callback (or returning a promise if no callback is provided).
87
87
 
88
- Implements [`Dispatcher.destroy([error, callback])`](docs/api/Dispatcher.md#dispatcher-callback-).
89
-
90
88
  ### `Client.connect(options[, callback])`
91
89
 
92
- See [`Dispatcher.connect(options[, callback])`](docs/api/Dispatcher.md#clientconnectoptions--callback).
90
+ See [`Dispatcher.connect(options[, callback])`](Dispatcher.md#dispatcherconnectoptions-callback).
93
91
 
94
92
  ### `Client.dispatch(options, handlers)`
95
93
 
96
- Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
94
+ Implements [`Dispatcher.dispatch(options, handlers)`](Dispatcher.md#dispatcherdispatchoptions-handler).
97
95
 
98
96
  ### `Client.pipeline(options, handler)`
99
97
 
100
- See [`Dispatcher.pipeline(options, handler)`](docs/api/Dispatcher.md#clientpipelineoptions-handler).
98
+ See [`Dispatcher.pipeline(options, handler)`](Dispatcher.md#dispatcherpipelineoptions-handler).
101
99
 
102
100
  ### `Client.request(options[, callback])`
103
101
 
104
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
102
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
105
103
 
106
104
  ### `Client.stream(options, factory[, callback])`
107
105
 
108
- See [`Dispatcher.stream(options, factory[, callback])`](docs/api/Dispatcher.md#clientstreamoptions-factory--callback).
106
+ See [`Dispatcher.stream(options, factory[, callback])`](Dispatcher.md#dispatcherstreamoptions-factory-callback).
109
107
 
110
108
  ### `Client.upgrade(options[, callback])`
111
109
 
112
- See [`Dispatcher.upgrade(options[, callback])`](docs/api/Dispatcher.md#clientupgradeoptions-callback).
110
+ See [`Dispatcher.upgrade(options[, callback])`](Dispatcher.md#dispatcherupgradeoptions-callback).
113
111
 
114
112
  ## Instance Properties
115
113
 
@@ -135,7 +133,7 @@ Property to get and set the pipelining factor.
135
133
 
136
134
  ### Event: `'connect'`
137
135
 
138
- See [Dispatcher Event: `'connect'`](docs/api/Dispatcher.md#event-connect).
136
+ See [Dispatcher Event: `'connect'`](Dispatcher.md#event-connect).
139
137
 
140
138
  Parameters:
141
139
 
@@ -181,7 +179,7 @@ try {
181
179
 
182
180
  ### Event: `'disconnect'`
183
181
 
184
- See [Dispatcher Event: `'disconnect'`](docs/api/Dispatcher.md#event-disconnect).
182
+ See [Dispatcher Event: `'disconnect'`](Dispatcher.md#event-disconnect).
185
183
 
186
184
  Parameters:
187
185
 
@@ -224,9 +222,9 @@ try {
224
222
 
225
223
  ### Event: `'drain'`
226
224
 
227
- Emitted when pipeline is no longer [`busy`](#clientbusy).
225
+ Emitted when pipeline is no longer busy.
228
226
 
229
- See [Dispatcher Event: `'drain'`](docs/api/Dispatcher.md#event-drain).
227
+ See [Dispatcher Event: `'drain'`](Dispatcher.md#event-drain).
230
228
 
231
229
  #### Example - Client drain event
232
230
 
@@ -791,11 +791,11 @@ Emitted when dispatcher is no longer busy.
791
791
 
792
792
  * `http.IncomingHttpHeaders | string[] | null`
793
793
 
794
- Header arguments such as `options.headers` in [`Client.dispatch`](./Client.md#client-dispatchoptions-handlers) can be specified in two forms; either as an object specified by the `http.IncomingHttpHeaders` type, or an array of strings. An array representation of a header list must have an even length or an `InvalidArgumentError` will be thrown.
794
+ Header arguments such as `options.headers` in [`Client.dispatch`](Client.md#clientdispatchoptions-handlers) can be specified in two forms; either as an object specified by the `http.IncomingHttpHeaders` type, or an array of strings. An array representation of a header list must have an even length or an `InvalidArgumentError` will be thrown.
795
795
 
796
796
  Keys are lowercase and values are not modified.
797
797
 
798
- Response headers will derive a `host` from the `url` of the [Client](#class-client) instance if no `host` header was previously specified.
798
+ Response headers will derive a `host` from the `url` of the [Client](Client.md#class-client) instance if no `host` header was previously specified.
799
799
 
800
800
  ### Example 1 - Object
801
801
 
@@ -14,7 +14,7 @@ Returns: `MockAgent`
14
14
 
15
15
  ### Parameter: `MockAgentOptions`
16
16
 
17
- Extends: [`AgentOptions`](docs/api/Agent.md#parameter-agentoptions)
17
+ Extends: [`AgentOptions`](Agent.md#parameter-agentoptions)
18
18
 
19
19
  * **agent** `Agent` (optional) - Default: `new Agent([options])` - a custom agent encapsulated by the MockAgent.
20
20
 
@@ -314,11 +314,11 @@ await mockAgent.close()
314
314
 
315
315
  ### `MockAgent.dispatch(options, handlers)`
316
316
 
317
- Implements [`Agent.dispatch(options, handlers)`](docs/api/Agent.md#parameter-agentdispatchoptions).
317
+ Implements [`Agent.dispatch(options, handlers)`](Agent.md#parameter-agentdispatchoptions).
318
318
 
319
319
  ### `MockAgent.request(options[, callback])`
320
320
 
321
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
321
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
322
322
 
323
323
  #### Example - MockAgent request
324
324
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Extends: `undici.Client`
4
4
 
5
- A mock client class that implements the same api as [MockPool](docs/api/MockPool.md).
5
+ A mock client class that implements the same api as [MockPool](MockPool.md).
6
6
 
7
7
  ## `new MockClient(origin, [options])`
8
8
 
@@ -36,19 +36,19 @@ const mockClient = mockAgent.get('http://localhost:3000')
36
36
 
37
37
  ### `MockClient.intercept(options)`
38
38
 
39
- Implements: [`MockPool.intercept(options)`](docs/api/MockPool.md#mockpoolinterceptoptions)
39
+ Implements: [`MockPool.intercept(options)`](MockPool.md#mockpoolinterceptoptions)
40
40
 
41
41
  ### `MockClient.close()`
42
42
 
43
- Implements: [`MockPool.close()`](docs/api/MockPool.md#mockpoolclose)
43
+ Implements: [`MockPool.close()`](MockPool.md#mockpoolclose)
44
44
 
45
45
  ### `MockClient.dispatch(options, handlers)`
46
46
 
47
- Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
47
+ Implements [`Dispatcher.dispatch(options, handlers)`](Dispatcher.md#dispatcherdispatchoptions-handler).
48
48
 
49
49
  ### `MockClient.request(options[, callback])`
50
50
 
51
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
51
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
52
52
 
53
53
  #### Example - MockClient request
54
54
 
@@ -62,12 +62,14 @@ Returns: `MockInterceptor` corresponding to the input options.
62
62
 
63
63
  We can define the behaviour of an intercepted request with the following options.
64
64
 
65
- * **reply** `(statusCode: number, replyData: string | object, responseOptions?: MockResponseOptions) => MockScope` - define a reply for a matching request. Default for `responseOptions` is `{}`.
65
+ * **reply** `(statusCode: number, replyData: string | Buffer | object, responseOptions?: MockResponseOptions) => MockScope` - define a reply for a matching request. Default for `responseOptions` is `{}`.
66
66
  * **replyWithError** `(error: Error) => MockScope` - define an error for a matching request to throw.
67
67
  * **defaultReplyHeaders** `(headers: Record<string, string>) => MockInterceptor` - define default headers to be included in subsequent replies. These are in addition to headers on a specific reply.
68
68
  * **defaultReplyTrailers** `(trailers: Record<string, string>) => MockInterceptor` - define default trailers to be included in subsequent replies. These are in addition to trailers on a specific reply.
69
69
  * **replyContentLength** `() => MockInterceptor` - define automatically calculated `content-length` headers to be included in subsequent replies.
70
70
 
71
+ The reply data of an intercepted request may either be a string, buffer, or JavaScript object. Objects are converted to JSON while strings and buffers are sent as-is.
72
+
71
73
  By default, `reply` and `replyWithError` define the behaviour for the first matching request only. Subsequent requests will not be affected (this can be changed using the returned `MockScope`).
72
74
 
73
75
  ### Parameter: `MockResponseOptions`
@@ -297,7 +299,7 @@ mockPool.intercept({
297
299
  }).defaultReplyTrailers({ foo: 'bar' })
298
300
  .reply(200, 'foo')
299
301
 
300
- const { trailers } = await request('http://localhost:3000/foo')
302
+ const { trailers } = await request('http://localhost:3000/foo')
301
303
 
302
304
  console.log('trailers', trailers) // trailers { foo: 'bar' }
303
305
  ```
@@ -410,11 +412,11 @@ await mockPool.close()
410
412
 
411
413
  ### `MockPool.dispatch(options, handlers)`
412
414
 
413
- Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
415
+ Implements [`Dispatcher.dispatch(options, handlers)`](Dispatcher.md#dispatcherdispatchoptions-handler).
414
416
 
415
417
  ### `MockPool.request(options[, callback])`
416
418
 
417
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
419
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
418
420
 
419
421
  #### Example - MockPool request
420
422
 
package/docs/api/Pool.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Extends: `undici.Dispatcher`
4
4
 
5
- A pool of [Client](docs/api/Client.md) instances connected to the same upstream target.
5
+ A pool of [Client](Client.md) instances connected to the same upstream target.
6
6
 
7
7
  Requests are not guaranteed to be dispatched in order of invocation.
8
8
 
@@ -15,7 +15,7 @@ Arguments:
15
15
 
16
16
  ### Parameter: `PoolOptions`
17
17
 
18
- Extends: [`ClientOptions`](docs/api/Client.md#parameter-clientoptions)
18
+ Extends: [`ClientOptions`](Client.md#parameter-clientoptions)
19
19
 
20
20
  * **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Client(origin, opts)`
21
21
  * **connections** `number | null` (optional) - Default: `null` - The number of `Client` instances to create. When set to `null`, the `Pool` instance will create an unlimited amount of `Client` instances.
@@ -24,56 +24,56 @@ Extends: [`ClientOptions`](docs/api/Client.md#parameter-clientoptions)
24
24
 
25
25
  ### `Pool.closed`
26
26
 
27
- Implements [Client.closed](docs/api/Client.md#clientclosed)
27
+ Implements [Client.closed](Client.md#clientclosed)
28
28
 
29
29
  ### `Pool.destroyed`
30
30
 
31
- Implements [Client.destroyed](docs/api/Client.md#clientdestroyed)
31
+ Implements [Client.destroyed](Client.md#clientdestroyed)
32
32
 
33
33
  ## Instance Methods
34
34
 
35
35
  ### `Pool.close([callback])`
36
36
 
37
- Implements [`Dispatcher.close([callback])`](docs/api/Dispatcher.md#clientclose-callback-).
37
+ Implements [`Dispatcher.close([callback])`](Dispatcher.md#dispatcherclosecallback-promise).
38
38
 
39
39
  ### `Pool.destroy([error, callback])`
40
40
 
41
- Implements [`Dispatcher.destroy([error, callback])`](docs/api/Dispatcher.md#dispatcher-callback-).
41
+ Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
42
42
 
43
43
  ### `Pool.connect(options[, callback])`
44
44
 
45
- See [`Dispatcher.connect(options[, callback])`](docs/api/Dispatcher.md#clientconnectoptions--callback).
45
+ See [`Dispatcher.connect(options[, callback])`](Dispatcher.md#dispatcherconnectoptions-callback).
46
46
 
47
- ### `Pool.dispatch(options, handlers)`
47
+ ### `Pool.dispatch(options, handler)`
48
48
 
49
- Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
49
+ Implements [`Dispatcher.dispatch(options, handler)`](Dispatcher.md#dispatcherdispatchoptions-handler).
50
50
 
51
51
  ### `Pool.pipeline(options, handler)`
52
52
 
53
- See [`Dispatcher.pipeline(options, handler)`](docs/api/Dispatcher.md#clientpipelineoptions-handler).
53
+ See [`Dispatcher.pipeline(options, handler)`](Dispatcher.md#dispatcherpipelineoptions-handler).
54
54
 
55
55
  ### `Pool.request(options[, callback])`
56
56
 
57
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
57
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
58
58
 
59
59
  ### `Pool.stream(options, factory[, callback])`
60
60
 
61
- See [`Dispatcher.stream(options, factory[, callback])`](docs/api/Dispatcher.md#clientstreamoptions-factory--callback).
61
+ See [`Dispatcher.stream(options, factory[, callback])`](Dispatcher.md#dispatcherstreamoptions-factory-callback).
62
62
 
63
63
  ### `Pool.upgrade(options[, callback])`
64
64
 
65
- See [`Dispatcher.upgrade(options[, callback])`](docs/api/Dispatcher.md#clientupgradeoptions-callback).
65
+ See [`Dispatcher.upgrade(options[, callback])`](Dispatcher.md#dispatcherupgradeoptions-callback).
66
66
 
67
67
  ## Instance Events
68
68
 
69
69
  ### Event: `'connect'`
70
70
 
71
- See [Dispatcher Event: `'connect'`](docs/api/Dispatcher.md#event-connect).
71
+ See [Dispatcher Event: `'connect'`](Dispatcher.md#event-connect).
72
72
 
73
73
  ### Event: `'disconnect'`
74
74
 
75
- See [Dispatcher Event: `'disconnect'`](docs/api/Dispatcher.md#event-connect).
75
+ See [Dispatcher Event: `'disconnect'`](Dispatcher.md#event-disconnect).
76
76
 
77
77
  ### Event: `'drain'`
78
78
 
79
- See [Dispatcher Event: `'drain'`](docs/api/Dispatcher.md#event-connect).
79
+ See [Dispatcher Event: `'drain'`](Dispatcher.md#event-drain).
@@ -14,7 +14,7 @@ Returns: `ProxyAgent`
14
14
 
15
15
  ### Parameter: `ProxyAgentOptions`
16
16
 
17
- Extends: [`AgentOptions`](docs/api/Agent.md#parameter-agentoptions)
17
+ Extends: [`AgentOptions`](Agent.md#parameter-agentoptions)
18
18
 
19
19
  * **uri** `string` (required) - It can be passed either by a string or a object containing `uri` as string.
20
20
 
@@ -93,8 +93,8 @@ await proxyAgent.close()
93
93
 
94
94
  ### `ProxyAgent.dispatch(options, handlers)`
95
95
 
96
- Implements [`Agent.dispatch(options, handlers)`](docs/api/Agent.md#parameter-agentdispatchoptions).
96
+ Implements [`Agent.dispatch(options, handlers)`](Agent.md#parameter-agentdispatchoptions).
97
97
 
98
98
  ### `ProxyAgent.request(options[, callback])`
99
99
 
100
- See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
100
+ See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
@@ -1,6 +1,6 @@
1
1
  # Client Lifecycle
2
2
 
3
- An Undici [Client](docs/api/Client.md) can be best described as a state machine. The following list is a summary of the various state transitions the `Client` will go through in its lifecycle. This document also contains detailed breakdowns of each state.
3
+ An Undici [Client](Client.md) can be best described as a state machine. The following list is a summary of the various state transitions the `Client` will go through in its lifecycle. This document also contains detailed breakdowns of each state.
4
4
 
5
5
  > This diagram is not a perfect representation of the undici Client. Since the Client class is not actually implemented as a state-machine, actual execution may deviate slightly from what is described below. Consider this as a general resource for understanding the inner workings of the Undici client rather than some kind of formal specification.
6
6
 
@@ -29,25 +29,25 @@ An Undici [Client](docs/api/Client.md) can be best described as a state machine.
29
29
 
30
30
  ### idle
31
31
 
32
- The **idle** state is the initial state of a `Client` instance. While an `origin` is required for instantiating a `Client` instance, the underlying socket connection will not be established until a request is queued using [`Client.dispatch()`](docs/api/Client.md#clientdispatchoptions-handlers). By calling `Client.dispatch()` directly or using one of the multiple implementations ([`Client.connect()`](docs/api/Client.md#clientconnectoptions--callback), [`Client.pipeline()`](docs/api/Client.md#clientpipelineoptions-handler), [`Client.request()`](docs/api/Client.md#clientrequestoptions--callback), [`Client.stream()`](docs/api/Client.md#clientstreamoptions-factory--callback), and [`Client.upgrade()`](docs/api/Client.md#clientupgradeoptions-callback)), the `Client` instance will transition from **idle** to [**pending**](#pending) and then most likely directly to [**processing**](#processing).
32
+ The **idle** state is the initial state of a `Client` instance. While an `origin` is required for instantiating a `Client` instance, the underlying socket connection will not be established until a request is queued using [`Client.dispatch()`](Client.md#clientdispatchoptions-handlers). By calling `Client.dispatch()` directly or using one of the multiple implementations ([`Client.connect()`](Client.md#clientconnectoptions-callback), [`Client.pipeline()`](Client.md#clientpipelineoptions-handler), [`Client.request()`](Client.md#clientrequestoptions-callback), [`Client.stream()`](Client.md#clientstreamoptions-factory-callback), and [`Client.upgrade()`](Client.md#clientupgradeoptions-callback)), the `Client` instance will transition from **idle** to [**pending**](#pending) and then most likely directly to [**processing**](#processing).
33
33
 
34
- Calling [`Client.close()`](docs/api/Client.md#clientclose-callback-) or [`Client.destroy()`](docs/api/Client.md#clientdestroyerror) transitions directly to the [**destroyed**](#destroyed) state since the `Client` instance will have no queued requests in this state.
34
+ Calling [`Client.close()`](Client.md#clientclosecallback) or [`Client.destroy()`](Client.md#clientdestroyerror-callback) transitions directly to the [**destroyed**](#destroyed) state since the `Client` instance will have no queued requests in this state.
35
35
 
36
36
  ### pending
37
37
 
38
- The **pending** state signifies a non-processing `Client`. Upon entering this state, the `Client` establishes a socket connection and emits the [`'connect'`](docs/api/Client.md#event-connect) event signalling a connection was successfully established with the `origin` provided during `Client` instantiation. The internal queue is initially empty, and requests can start queueing.
38
+ The **pending** state signifies a non-processing `Client`. Upon entering this state, the `Client` establishes a socket connection and emits the [`'connect'`](Client.md#event-connect) event signalling a connection was successfully established with the `origin` provided during `Client` instantiation. The internal queue is initially empty, and requests can start queueing.
39
39
 
40
- Calling [`Client.close()`](docs/api/Client.md#clientclose-callback-) with queued requests, transitions the `Client` to the [**processing**](#processing) state. Without queued requests, it transitions to the [**destroyed**](#destroyed) state.
40
+ Calling [`Client.close()`](Client.md#clientclosecallback) with queued requests, transitions the `Client` to the [**processing**](#processing) state. Without queued requests, it transitions to the [**destroyed**](#destroyed) state.
41
41
 
42
- Calling [`Client.destroy()`](docs/api/Client.md#clientdestroyerror) transitions directly to the [**destroyed**](#destroyed) state regardless of existing requests.
42
+ Calling [`Client.destroy()`](Client.md#clientdestroyerror-callback) transitions directly to the [**destroyed**](#destroyed) state regardless of existing requests.
43
43
 
44
44
  ### processing
45
45
 
46
- The **processing** state is a state machine within itself. It initializes to the [**processing.running**](#running) state. The [`Client.dispatch()`](docs/api/Client.md#clientdispatchoptions-handlers), [`Client.close()`](docs/api/Client.md#clientclose-callback-), and [`Client.destroy()`](docs/api/Client.md#clientdestroyerror) can be called at any time while the `Client` is in this state. `Client.dispatch()` will add more requests to the queue while existing requests continue to be processed. `Client.close()` will transition to the [**processing.closing**](#closing) state. And `Client.destroy()` will transition to [**destroyed**](#destroyed).
46
+ The **processing** state is a state machine within itself. It initializes to the [**processing.running**](#running) state. The [`Client.dispatch()`](Client.md#clientdispatchoptions-handlers), [`Client.close()`](Client.md#clientclosecallback), and [`Client.destroy()`](Client.md#clientdestroyerror-callback) can be called at any time while the `Client` is in this state. `Client.dispatch()` will add more requests to the queue while existing requests continue to be processed. `Client.close()` will transition to the [**processing.closing**](#closing) state. And `Client.destroy()` will transition to [**destroyed**](#destroyed).
47
47
 
48
48
  #### running
49
49
 
50
- In the **processing.running** sub-state, queued requests are being processed in a FIFO order. If a request body requires draining, the *needDrain* event transitions to the [**processing.busy**](#busy) sub-state. The *close* event transitions the Client to the [**process.closing**](#closing) sub-state. If all queued requests are processed and neither [`Client.close()`](docs/api/Client.md#clientclose-callback-) nor [`Client.destroy()`](docs/api/Client.md#clientdestroyerror) are called, then the [**processing**](#processing) machine will trigger a *keepalive* event transitioning the `Client` back to the [**pending**](#pending) state. During this time, the `Client` is waiting for the socket connection to timeout, and once it does, it triggers the *timeout* event and transitions to the [**idle**](#idle) state.
50
+ In the **processing.running** sub-state, queued requests are being processed in a FIFO order. If a request body requires draining, the *needDrain* event transitions to the [**processing.busy**](#busy) sub-state. The *close* event transitions the Client to the [**process.closing**](#closing) sub-state. If all queued requests are processed and neither [`Client.close()`](Client.md#clientclosecallback) nor [`Client.destroy()`](Client.md#clientdestroyerror-callback) are called, then the [**processing**](#processing) machine will trigger a *keepalive* event transitioning the `Client` back to the [**pending**](#pending) state. During this time, the `Client` is waiting for the socket connection to timeout, and once it does, it triggers the *timeout* event and transitions to the [**idle**](#idle) state.
51
51
 
52
52
  #### busy
53
53
 
@@ -55,7 +55,7 @@ This sub-state is only entered when a request body is an instance of [Stream](ht
55
55
 
56
56
  #### closing
57
57
 
58
- This sub-state is only entered when a `Client` instance has queued requests and the [`Client.close()`](docs/api/Client.md#clientclose-callback-) method is called. In this state, the `Client` instance continues to process requests as usual, with the one exception that no additional requests can be queued. Once all of the queued requests are processed, the `Client` will trigger the *done* event gracefully entering the [**destroyed**](#destroyed) state without an error.
58
+ This sub-state is only entered when a `Client` instance has queued requests and the [`Client.close()`](Client.md#clientclosecallback) method is called. In this state, the `Client` instance continues to process requests as usual, with the one exception that no additional requests can be queued. Once all of the queued requests are processed, the `Client` will trigger the *done* event gracefully entering the [**destroyed**](#destroyed) state without an error.
59
59
 
60
60
  ### destroyed
61
61
 
package/index.d.ts CHANGED
@@ -41,4 +41,5 @@ declare namespace Undici {
41
41
  var MockPool: typeof import('./types/mock-pool');
42
42
  var MockAgent: typeof import('./types/mock-agent');
43
43
  var mockErrors: typeof import('./types/mock-errors');
44
+ var fetch: typeof import('./types/fetch').fetch;
44
45
  }
package/lib/core/util.js CHANGED
@@ -241,7 +241,7 @@ function isDisturbed (body) {
241
241
  (stream.isDisturbed && stream.isDisturbed(body)) ||
242
242
  body[kBodyUsed] ||
243
243
  body.readableDidRead || (state && state.dataEmitted) ||
244
- isAborted(stream)
244
+ isAborted(body)
245
245
  ))
246
246
  }
247
247
 
@@ -1,13 +1,12 @@
1
1
  'use strict'
2
2
 
3
- const { Blob } = require('buffer')
3
+ const { isBlobLike, toUSVString } = require('./util')
4
4
  const { kState } = require('./symbols')
5
5
  const { File } = require('./file')
6
- const { HTMLFormElement, toUSVString } = require('./util')
7
6
 
8
7
  class FormData {
9
8
  constructor (...args) {
10
- if (args.length > 0 && !(args[0] instanceof HTMLFormElement)) {
9
+ if (args.length > 0 && !(args[0]?.constructor?.name === 'HTMLFormElement')) {
11
10
  throw new TypeError(
12
11
  "Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'"
13
12
  )
@@ -25,7 +24,7 @@ class FormData {
25
24
  `Failed to execute 'append' on 'FormData': 2 arguments required, but only ${args.length} present.`
26
25
  )
27
26
  }
28
- if (args.length === 3 && !(args[1] instanceof Blob)) {
27
+ if (args.length === 3 && !isBlobLike(args[1])) {
29
28
  throw new TypeError(
30
29
  "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'"
31
30
  )
@@ -34,7 +33,7 @@ class FormData {
34
33
  const filename = args.length === 3 ? toUSVString(args[2]) : undefined
35
34
 
36
35
  // 1. Let value be value if given; otherwise blobValue.
37
- const value = args[1] instanceof Blob ? args[1] : toUSVString(args[1])
36
+ const value = isBlobLike(args[1]) ? args[1] : toUSVString(args[1])
38
37
 
39
38
  // 2. Let entry be the result of creating an entry with
40
39
  // name, value, and filename if given.
@@ -135,7 +134,7 @@ class FormData {
135
134
  `Failed to execute 'set' on 'FormData': 2 arguments required, but only ${args.length} present.`
136
135
  )
137
136
  }
138
- if (args.length === 3 && !(args[1] instanceof Blob)) {
137
+ if (args.length === 3 && !isBlobLike(args[1])) {
139
138
  throw new TypeError(
140
139
  "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'"
141
140
  )
@@ -147,7 +146,7 @@ class FormData {
147
146
  // are:
148
147
 
149
148
  // 1. Let value be value if given; otherwise blobValue.
150
- const value = args[1] instanceof Blob ? args[1] : toUSVString(args[1])
149
+ const value = isBlobLike(args[1]) ? args[1] : toUSVString(args[1])
151
150
 
152
151
  // 2. Let entry be the result of creating an entry with name, value, and
153
152
  // filename if given.
@@ -168,6 +167,28 @@ class FormData {
168
167
  }
169
168
  }
170
169
 
170
+ get [Symbol.toStringTag] () {
171
+ return 'FormData'
172
+ }
173
+
174
+ * entries () {
175
+ for (const pair of this) {
176
+ yield pair
177
+ }
178
+ }
179
+
180
+ * keys () {
181
+ for (const [key] of this) {
182
+ yield key
183
+ }
184
+ }
185
+
186
+ * values () {
187
+ for (const [, value] of this) {
188
+ yield value
189
+ }
190
+ }
191
+
171
192
  * [Symbol.iterator] () {
172
193
  // The value pairs to iterate over are this’s entry list’s entries with
173
194
  // the key being the name and the value being the value.
@@ -192,7 +213,7 @@ function makeEntry (name, value, filename) {
192
213
 
193
214
  // 3. If value is a Blob object and not a File object, then set value to a new File
194
215
  // object, representing the same bytes, whose name attribute value is "blob".
195
- if (value instanceof Blob && !(value instanceof File)) {
216
+ if (isBlobLike(value) && !(value instanceof File)) {
196
217
  value = new File([value], 'blob')
197
218
  }
198
219
 
@@ -6,10 +6,6 @@ const { validateHeaderName, validateHeaderValue } = require('http')
6
6
  const { kHeadersList } = require('../core/symbols')
7
7
  const { kGuard } = require('./symbols')
8
8
  const { kEnumerableProperty } = require('../core/util')
9
- const {
10
- InvalidHTTPTokenError,
11
- HTTPInvalidHeaderValueError
12
- } = require('../core/errors')
13
9
  const {
14
10
  forbiddenHeaderNames,
15
11
  forbiddenResponseHeaderNames
@@ -34,7 +30,7 @@ function binarySearch (arr, val) {
34
30
 
35
31
  function normalizeAndValidateHeaderName (name) {
36
32
  if (name === undefined) {
37
- throw new InvalidHTTPTokenError(`Header name ${name}`)
33
+ throw new TypeError(`Header name ${name}`)
38
34
  }
39
35
  const normalizedHeaderName = name.toLocaleLowerCase()
40
36
  validateHeaderName(normalizedHeaderName)
@@ -43,7 +39,7 @@ function normalizeAndValidateHeaderName (name) {
43
39
 
44
40
  function normalizeAndValidateHeaderValue (name, value) {
45
41
  if (value === undefined) {
46
- throw new HTTPInvalidHeaderValueError(value, name)
42
+ throw new TypeError(value, name)
47
43
  }
48
44
  const normalizedHeaderValue = `${value}`.replace(
49
45
  /^[\n\t\r\x20]+|[\n\t\r\x20]+$/g,
@@ -737,7 +737,7 @@ function fetchFinale (fetchParams, response) {
737
737
 
738
738
  // TODO (spec): The spec doesn't specify this but we need to
739
739
  // terminate fetch if we have an error response.
740
- if (response.status === 0) {
740
+ if (response.type === 'error') {
741
741
  context.terminate({ reason: response.error })
742
742
  }
743
743
  }
@@ -105,7 +105,7 @@ class Response {
105
105
 
106
106
  // 1. If init["status"] is not in the range 200 to 599, inclusive, then
107
107
  // throw a RangeError.
108
- if ('status' in init) {
108
+ if ('status' in init && init.status !== undefined) {
109
109
  if (!Number.isFinite(init.status)) {
110
110
  throw new TypeError()
111
111
  }
@@ -117,7 +117,7 @@ class Response {
117
117
  }
118
118
  }
119
119
 
120
- if ('statusText' in init) {
120
+ if ('statusText' in init && init.statusText !== undefined) {
121
121
  // 2. If init["statusText"] does not match the reason-phrase token
122
122
  // production, then throw a TypeError.
123
123
  // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2:
@@ -139,12 +139,12 @@ class Response {
139
139
  this[kHeaders][kRealm] = this[kRealm]
140
140
 
141
141
  // 5. Set this’s response’s status to init["status"].
142
- if ('status' in init) {
142
+ if ('status' in init && init.status !== undefined) {
143
143
  this[kState].status = init.status
144
144
  }
145
145
 
146
146
  // 6. Set this’s response’s status message to init["statusText"].
147
- if ('statusText' in init) {
147
+ if ('statusText' in init && init.statusText !== undefined) {
148
148
  this[kState].statusText = String(init.statusText)
149
149
  }
150
150
 
package/lib/fetch/util.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { redirectStatus } = require('./constants')
4
4
  const { performance } = require('perf_hooks')
5
+ const { Blob } = require('buffer')
5
6
  const nodeUtil = require('util')
6
7
 
7
8
  let ReadableStream
@@ -68,6 +69,18 @@ function requestBadPort (request) {
68
69
  return 'allowed'
69
70
  }
70
71
 
72
+ // based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License)
73
+ function isBlobLike (object) {
74
+ return object instanceof Blob || (
75
+ object &&
76
+ typeof object === 'object' &&
77
+ typeof object.constructor === 'function' &&
78
+ (typeof object.stream === 'function' ||
79
+ typeof object.arrayBuffer === 'function') &&
80
+ /^(Blob|File)$/.test(object[Symbol.toStringTag])
81
+ )
82
+ }
83
+
71
84
  // Check whether |statusText| is a ByteString and
72
85
  // matches the Reason-Phrase token production.
73
86
  // RFC 2616: https://tools.ietf.org/html/rfc2616
@@ -229,7 +242,47 @@ function appendFetchMetadata (httpRequest) {
229
242
 
230
243
  // https://fetch.spec.whatwg.org/#append-a-request-origin-header
231
244
  function appendRequestOriginHeader (request) {
232
- // TODO
245
+ // 1. Let serializedOrigin be the result of byte-serializing a request origin with request.
246
+ let serializedOrigin = request.origin
247
+
248
+ // 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list.
249
+ if (request.responseTainting === 'cors' || request.mode === 'websocket') {
250
+ if (serializedOrigin) {
251
+ request.headersList.append('Origin', serializedOrigin)
252
+ }
253
+ }
254
+
255
+ // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
256
+ else if (request.method !== 'GET' && request.method !== 'HEAD') {
257
+ // 1. Switch on request’s referrer policy:
258
+ switch (request.referrerPolicy) {
259
+ case 'no-referrer':
260
+ // Set serializedOrigin to `null`.
261
+ serializedOrigin = null
262
+ break
263
+ case 'no-referrer-when-downgrade':
264
+ case 'strict-origin':
265
+ case 'strict-origin-when-cross-origin':
266
+ // If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`.
267
+ if (/^https:/.test(request.origin) && !/^https:/.test(requestCurrentURL(request))) {
268
+ serializedOrigin = null
269
+ }
270
+ break
271
+ case 'same-origin':
272
+ // If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`.
273
+ if (request.origin !== requestCurrentURL(request).origin) {
274
+ serializedOrigin = null
275
+ }
276
+ break
277
+ default:
278
+ // Do nothing.
279
+ }
280
+
281
+ if (serializedOrigin) {
282
+ // 2. Append (`Origin`, serializedOrigin) to request’s header list.
283
+ request.headersList.append('Origin', serializedOrigin)
284
+ }
285
+ }
233
286
  }
234
287
 
235
288
  function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) {
@@ -284,10 +337,8 @@ function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) {
284
337
  class ServiceWorkerGlobalScope {} // dummy
285
338
  class Window {} // dummy
286
339
  class EnvironmentSettingsObject {} // dummy
287
- class HTMLFormElement {} // dummy
288
340
 
289
341
  module.exports = {
290
- HTMLFormElement,
291
342
  ServiceWorkerGlobalScope,
292
343
  Window,
293
344
  EnvironmentSettingsObject,
@@ -311,5 +362,6 @@ module.exports = {
311
362
  requestCurrentURL,
312
363
  responseURL,
313
364
  responseLocationURL,
365
+ isBlobLike,
314
366
  isValidReasonPhrase
315
367
  }
@@ -47,7 +47,13 @@ function matchKey (mockDispatch, { path, method, body, headers }) {
47
47
  }
48
48
 
49
49
  function getResponseData (data) {
50
- return typeof data === 'object' ? JSON.stringify(data) : data.toString()
50
+ if (Buffer.isBuffer(data)) {
51
+ return data
52
+ } else if (typeof data === 'object') {
53
+ return JSON.stringify(data)
54
+ } else {
55
+ return data.toString()
56
+ }
51
57
  }
52
58
 
53
59
  function getMockDispatch (mockDispatches, key) {
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { kClients, kProxy } = require('./core/symbols')
3
+ const { kProxy } = require('./core/symbols')
4
4
  const url = require('url')
5
5
  const Agent = require('./agent')
6
6
  const Dispatcher = require('./dispatcher')
@@ -12,11 +12,7 @@ class ProxyAgent extends Dispatcher {
12
12
  constructor (opts) {
13
13
  super(opts)
14
14
  this[kProxy] = buildProxyOptions(opts)
15
-
16
- const agent = new Agent(opts)
17
- this[kAgent] = agent
18
-
19
- this[kClients] = agent[kClients]
15
+ this[kAgent] = new Agent(opts)
20
16
  }
21
17
 
22
18
  dispatch (opts, handler) {
@@ -29,7 +25,7 @@ class ProxyAgent extends Dispatcher {
29
25
  headers: {
30
26
  ...opts.headers,
31
27
  host
32
- },
28
+ }
33
29
  },
34
30
  handler
35
31
  )
@@ -37,11 +33,10 @@ class ProxyAgent extends Dispatcher {
37
33
 
38
34
  async close () {
39
35
  await this[kAgent].close()
40
- this[kClients].clear()
41
36
  }
42
37
  }
43
38
 
44
- function buildProxyOptions(opts) {
39
+ function buildProxyOptions (opts) {
45
40
  if (typeof opts === 'string') {
46
41
  opts = { uri: opts }
47
42
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "4.9.4",
3
+ "version": "4.10.2",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
@@ -19,6 +19,17 @@
19
19
  "author": true
20
20
  }
21
21
  ],
22
+ "keywords": [
23
+ "fetch",
24
+ "http",
25
+ "https",
26
+ "promise",
27
+ "request",
28
+ "curl",
29
+ "wget",
30
+ "xhr",
31
+ "whatwg"
32
+ ],
22
33
  "main": "index.js",
23
34
  "types": "index.d.ts",
24
35
  "files": [
@@ -63,6 +74,7 @@
63
74
  "cronometro": "^0.8.0",
64
75
  "delay": "^5.0.0",
65
76
  "docsify-cli": "^4.4.3",
77
+ "formdata-node": "^4.3.1",
66
78
  "https-pem": "^2.0.0",
67
79
  "husky": "^7.0.2",
68
80
  "jest": "^27.2.0",
@@ -21,7 +21,7 @@ declare class MockScope<TData extends object = object> {
21
21
  declare class MockInterceptor {
22
22
  constructor(options: MockInterceptor.Options, mockDispatches: MockInterceptor.MockDispatch[]);
23
23
  /** Mock an undici request with the defined reply. */
24
- reply<TData extends object = object>(statusCode: number, data: TData | string, responseOptions?: MockInterceptor.MockResponseOptions): MockScope<TData>;
24
+ reply<TData extends object = object>(statusCode: number, data: TData | Buffer| string , responseOptions?: MockInterceptor.MockResponseOptions): MockScope<TData>;
25
25
  /** Mock an undici request by throwing the defined reply error. */
26
26
  replyWithError<TError extends Error = Error>(error: TError): MockScope;
27
27
  /** Set default reply headers on the interceptor for subsequent mocked replies. */