undici 4.9.2 → 4.9.3

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.
@@ -25,10 +25,6 @@ See: [`PoolOptions`](docs/api/Pool.md#parameter-pooloptions)
25
25
 
26
26
  Returns an array of upstreams that were previously added.
27
27
 
28
- ### `BalancedPool.busy`
29
-
30
- Implements [Client.busy](docs/api/Client.md#clientbusy)
31
-
32
28
  ### `BalancedPool.closed`
33
29
 
34
30
  Implements [Client.closed](docs/api/Client.md#clientclosed)
@@ -113,12 +113,6 @@ See [`Dispatcher.upgrade(options[, callback])`](docs/api/Dispatcher.md#clientupg
113
113
 
114
114
  ## Instance Properties
115
115
 
116
- ### `Client.busy`
117
-
118
- * `boolean`
119
-
120
- `true` if pipeline is saturated or blocked. Indicates whether dispatching further requests is meaningful.
121
-
122
116
  ### `Client.closed`
123
117
 
124
118
  * `boolean`
@@ -161,7 +155,7 @@ const server = createServer((request, response) => {
161
155
  response.end('Hello, World!')
162
156
  }).listen()
163
157
 
164
- await once(server, 'listening')
158
+ await once(server, 'listening')
165
159
 
166
160
  const client = new Client(`http://localhost:${server.address().port}`)
167
161
 
@@ -251,7 +245,6 @@ const client = new Client(`http://localhost:${server.address().port}`)
251
245
 
252
246
  client.on('drain', () => {
253
247
  console.log('drain event')
254
- console.log(`Is Client busy: ${client.busy}`)
255
248
  client.close()
256
249
  server.close()
257
250
  })
@@ -262,8 +255,6 @@ const requests = [
262
255
  client.request({ path: '/', method: 'GET' })
263
256
  ]
264
257
 
265
- console.log(`Is Client busy: ${client.busy}`)
266
-
267
258
  await Promise.all(requests)
268
259
 
269
260
  console.log('requests completed')
@@ -177,14 +177,15 @@ try {
177
177
  ### `Dispatcher.dispatch(options, handler)`
178
178
 
179
179
  This is the low level API which all the preceding APIs are implemented on top of.
180
- This API is expected to evolve through semver-major versions and is less stable than the preceding higher level APIs. It is primarily intended for library developers who implement higher level APIs on top of this.
180
+ This API is expected to evolve through semver-major versions and is less stable than the preceding higher level APIs.
181
+ It is primarily intended for library developers who implement higher level APIs on top of this.
181
182
 
182
183
  Arguments:
183
184
 
184
185
  * **options** `DispatchOptions`
185
186
  * **handler** `DispatchHandler`
186
187
 
187
- Returns: `void`
188
+ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls won't make any progress until the `'drain'` event has been emitted.
188
189
 
189
190
  #### Parameter: `DispatchOptions`
190
191
 
@@ -330,7 +331,7 @@ Extends: [`RequestOptions`](#parameter-requestoptions)
330
331
  * **opaque** `unknown`
331
332
  * **body** `stream.Readable`
332
333
  * **context** `object`
333
- * **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
334
+ * **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
334
335
 
335
336
  #### Example 1 - Pipeline Echo
336
337
 
@@ -413,7 +414,7 @@ Extends: [`DispatchOptions`](#parameter-dispatchoptions)
413
414
 
414
415
  * **opaque** `unknown` (optional) - Default: `null` - Used for passing through context to `ResponseData`
415
416
  * **signal** `AbortSignal | events.EventEmitter | null` (optional) - Default: `null`
416
- * **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
417
+ * **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
417
418
 
418
419
  The `RequestOptions.method` property should not be value `'CONNECT'`.
419
420
 
@@ -581,7 +582,7 @@ Returns: `void | Promise<StreamData>` - Only returns a `Promise` if no `callback
581
582
  * **statusCode** `number`
582
583
  * **headers** `http.IncomingHttpHeaders`
583
584
  * **opaque** `unknown`
584
- * **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
585
+ * **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
585
586
 
586
587
  #### Parameter: `StreamData`
587
588
 
package/docs/api/Pool.md CHANGED
@@ -22,10 +22,6 @@ Extends: [`ClientOptions`](docs/api/Client.md#parameter-clientoptions)
22
22
 
23
23
  ## Instance Properties
24
24
 
25
- ### `Pool.busy`
26
-
27
- Implements [Client.busy](docs/api/Client.md#clientbusy)
28
-
29
25
  ### `Pool.closed`
30
26
 
31
27
  Implements [Client.closed](docs/api/Client.md#clientclosed)
@@ -59,4 +59,4 @@ This sub-state is only entered when a `Client` instance has queued requests and
59
59
 
60
60
  ### destroyed
61
61
 
62
- The **destroyed** state is a final state for the `Client` instance. Once in this state, a `Client` is nonfunctional. Calling any other `Client` methods will result in an `ClientDestroyedError`.
62
+ The **destroyed** state is a final state for the `Client` instance. Once in this state, a `Client` is nonfunctional. Calling any other `Client` methods will result in an `ClientDestroyedError`.
@@ -44,6 +44,8 @@ class BalancedPool extends Dispatcher {
44
44
  })
45
45
 
46
46
  pool.on('drain', (...args) => {
47
+ pool[kNeedDrain] = false
48
+
47
49
  if (this[kNeedDrain]) {
48
50
  this[kNeedDrain] = false
49
51
  this.emit('drain', ...args)
@@ -62,12 +64,16 @@ class BalancedPool extends Dispatcher {
62
64
  throw new BalancedPoolMissingUpstreamError()
63
65
  }
64
66
 
65
- let pool = this[kPools].shift()
66
- this[kPools].push(pool)
67
- if (pool.busy) {
68
- pool = this[kPools].find(pool => !pool.busy) || pool
67
+ const pool = this[kPools].find(pool => !pool[kNeedDrain]) || this[kPools][0]
68
+
69
+ if (!pool.dispatch(opts, handler)) {
70
+ pool[kNeedDrain] = true
71
+ this[kNeedDrain] = true
69
72
  }
70
- this[kNeedDrain] = !pool.dispatch(opts, handler)
73
+
74
+ this[kPools].splice(this[kPools].indexOf(pool), 1)
75
+ this[kPools].push(pool)
76
+
71
77
  return !this[kNeedDrain]
72
78
  }
73
79
 
@@ -87,10 +93,6 @@ class BalancedPool extends Dispatcher {
87
93
  return this[kPools].reduce((acc, pool) => acc && pool.destroyed, true)
88
94
  }
89
95
 
90
- get busy () {
91
- return this[kPools].reduce((acc, pool) => acc && pool.busy, true) || false
92
- }
93
-
94
96
  get closed () {
95
97
  return this[kPools].reduce((acc, pool) => acc && pool.closed, true)
96
98
  }
@@ -313,20 +313,23 @@ class Headers {
313
313
  }
314
314
 
315
315
  * keys () {
316
- for (let index = 0; index < this[kHeadersList].length; index += 2) {
317
- yield this[kHeadersList][index]
316
+ const clone = this[kHeadersList].slice()
317
+ for (let index = 0; index < clone.length; index += 2) {
318
+ yield clone[index]
318
319
  }
319
320
  }
320
321
 
321
322
  * values () {
322
- for (let index = 1; index < this[kHeadersList].length; index += 2) {
323
- yield this[kHeadersList][index]
323
+ const clone = this[kHeadersList].slice()
324
+ for (let index = 1; index < clone.length; index += 2) {
325
+ yield clone[index]
324
326
  }
325
327
  }
326
328
 
327
329
  * entries () {
328
- for (let index = 0; index < this[kHeadersList].length; index += 2) {
329
- yield [this[kHeadersList][index], this[kHeadersList][index + 1]]
330
+ const clone = this[kHeadersList].slice()
331
+ for (let index = 0; index < clone.length; index += 2) {
332
+ yield [clone[index], clone[index + 1]]
330
333
  }
331
334
  }
332
335
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "4.9.2",
3
+ "version": "4.9.3",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
package/types/agent.d.ts CHANGED
@@ -11,7 +11,7 @@ declare class Agent extends Dispatcher{
11
11
  /** `true` after `dispatcher.destroyed()` has been called or `dispatcher.close()` has been called and the dispatcher shutdown has completed. */
12
12
  destroyed: boolean;
13
13
  /** Dispatches a request. */
14
- dispatch(options: Agent.DispatchOptions, handler: Dispatcher.DispatchHandlers): void;
14
+ dispatch(options: Agent.DispatchOptions, handler: Dispatcher.DispatchHandlers): boolean;
15
15
  }
16
16
 
17
17
  declare namespace Agent {
@@ -11,7 +11,7 @@ export = Dispatcher;
11
11
  /** Dispatcher is the core API used to dispatch requests. */
12
12
  declare class Dispatcher extends EventEmitter {
13
13
  /** Dispatches a request. This API is expected to evolve through semver-major versions and is less stable than the preceding higher level APIs. It is primarily intended for library developers who implement higher level APIs on top of this. */
14
- dispatch(options: Dispatcher.DispatchOptions, handler: Dispatcher.DispatchHandlers): void;
14
+ dispatch(options: Dispatcher.DispatchOptions, handler: Dispatcher.DispatchHandlers): boolean;
15
15
  /** Starts two-way communications with the requested resource. */
16
16
  connect(options: Dispatcher.ConnectOptions): Promise<Dispatcher.ConnectData>;
17
17
  connect(options: Dispatcher.ConnectOptions, callback: (err: Error | null, data: Dispatcher.ConnectData) => void): void;
@@ -148,7 +148,7 @@ declare namespace Dispatcher {
148
148
  export type PipelineHandler = (data: PipelineHandlerData) => Readable;
149
149
  export type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH';
150
150
 
151
- /**
151
+ /**
152
152
  * @link https://fetch.spec.whatwg.org/#body-mixin
153
153
  */
154
154
  interface BodyMixin {
@@ -12,7 +12,7 @@ declare class MockAgent<TMockAgentOptions extends MockAgent.Options = MockAgent.
12
12
  get<TInterceptable extends Interceptable>(origin: RegExp): TInterceptable;
13
13
  get<TInterceptable extends Interceptable>(origin: ((origin: string) => boolean)): TInterceptable;
14
14
  /** Dispatches a mocked request. */
15
- dispatch(options: Agent.DispatchOptions, handler: Dispatcher.DispatchHandlers): void;
15
+ dispatch(options: Agent.DispatchOptions, handler: Dispatcher.DispatchHandlers): boolean;
16
16
  /** Closes the mock agent and waits for registered mock pools and clients to also close before resolving. */
17
17
  close(): Promise<void>;
18
18
  /** Disables mocking in MockAgent. */
@@ -11,7 +11,7 @@ declare class MockClient extends Client implements Interceptable {
11
11
  /** Intercepts any matching requests that use the same origin as this mock client. */
12
12
  intercept(options: MockInterceptor.Options): MockInterceptor;
13
13
  /** Dispatches a mocked request. */
14
- dispatch(options: Dispatcher.DispatchOptions, handlers: Dispatcher.DispatchHandlers): void;
14
+ dispatch(options: Dispatcher.DispatchOptions, handlers: Dispatcher.DispatchHandlers): boolean;
15
15
  /** Closes the mock client and gracefully waits for enqueued requests to complete. */
16
16
  close(): Promise<void>;
17
17
  }
@@ -11,7 +11,7 @@ declare class MockPool extends Pool implements Interceptable {
11
11
  /** Intercepts any matching requests that use the same origin as this mock pool. */
12
12
  intercept(options: MockInterceptor.Options): MockInterceptor;
13
13
  /** Dispatches a mocked request. */
14
- dispatch(options: Dispatcher.DispatchOptions, handlers: Dispatcher.DispatchHandlers): void;
14
+ dispatch(options: Dispatcher.DispatchOptions, handlers: Dispatcher.DispatchHandlers): boolean;
15
15
  /** Closes the mock pool and gracefully waits for enqueued requests to complete. */
16
16
  close(): Promise<void>;
17
17
  }
@@ -6,7 +6,7 @@ export = ProxyAgent
6
6
  declare class ProxyAgent extends Dispatcher {
7
7
  constructor(options: ProxyAgent.Options | string)
8
8
 
9
- dispatch(options: Agent.DispatchOptions, handler: Dispatcher.DispatchHandlers): void;
9
+ dispatch(options: Agent.DispatchOptions, handler: Dispatcher.DispatchHandlers): boolean;
10
10
  close(): Promise<void>;
11
11
  }
12
12