undici 6.9.0 → 6.10.1

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.
@@ -35,6 +35,12 @@ Extends: [`Dispatch.DispatchOptions`](Dispatcher.md#parameter-dispatchoptions).
35
35
  - `state`: `RetryState` - Current retry state. It can be mutated.
36
36
  - `opts`: `Dispatch.DispatchOptions & RetryOptions` - Options passed to the retry handler.
37
37
 
38
+ **`RetryState`**
39
+
40
+ It represents the retry state for a given request.
41
+
42
+ - `counter`: `number` - Current retry attempt.
43
+
38
44
  ### Parameter `RetryHandlers`
39
45
 
40
46
  - **dispatch** `(options: Dispatch.DispatchOptions, handlers: Dispatch.DispatchHandlers) => Promise<Dispatch.DispatchResponse>` (required) - Dispatch function to be called after every retry.
@@ -1,3 +1,4 @@
1
+ 'use strict'
1
2
  const assert = require('node:assert')
2
3
 
3
4
  const { kRetryHandlerDefaultRetry } = require('../core/symbols')
@@ -37,7 +38,7 @@ class RetryHandler {
37
38
  retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry],
38
39
  retryAfter: retryAfter ?? true,
39
40
  maxTimeout: maxTimeout ?? 30 * 1000, // 30s,
40
- timeout: minTimeout ?? 500, // .5s
41
+ minTimeout: minTimeout ?? 500, // .5s
41
42
  timeoutFactor: timeoutFactor ?? 2,
42
43
  maxRetries: maxRetries ?? 5,
43
44
  // What errors we should retry
@@ -59,6 +60,7 @@ class RetryHandler {
59
60
  }
60
61
 
61
62
  this.retryCount = 0
63
+ this.retryCountCheckpoint = 0
62
64
  this.start = 0
63
65
  this.end = null
64
66
  this.etag = null
@@ -104,17 +106,14 @@ class RetryHandler {
104
106
  const { method, retryOptions } = opts
105
107
  const {
106
108
  maxRetries,
107
- timeout,
109
+ minTimeout,
108
110
  maxTimeout,
109
111
  timeoutFactor,
110
112
  statusCodes,
111
113
  errorCodes,
112
114
  methods
113
115
  } = retryOptions
114
- let { counter, currentTimeout } = state
115
-
116
- currentTimeout =
117
- currentTimeout != null && currentTimeout > 0 ? currentTimeout : timeout
116
+ const { counter } = state
118
117
 
119
118
  // Any code that is not a Undici's originated and allowed to retry
120
119
  if (
@@ -159,9 +158,7 @@ class RetryHandler {
159
158
  const retryTimeout =
160
159
  retryAfterHeader > 0
161
160
  ? Math.min(retryAfterHeader, maxTimeout)
162
- : Math.min(currentTimeout * timeoutFactor ** counter, maxTimeout)
163
-
164
- state.currentTimeout = retryTimeout
161
+ : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout)
165
162
 
166
163
  setTimeout(() => cb(null), retryTimeout)
167
164
  }
@@ -309,10 +306,19 @@ class RetryHandler {
309
306
  return this.handler.onError(err)
310
307
  }
311
308
 
309
+ // We reconcile in case of a mix between network errors
310
+ // and server error response
311
+ if (this.retryCount - this.retryCountCheckpoint > 0) {
312
+ // We count the difference between the last checkpoint and the current retry count
313
+ this.retryCount = this.retryCountCheckpoint + (this.retryCount - this.retryCountCheckpoint)
314
+ } else {
315
+ this.retryCount += 1
316
+ }
317
+
312
318
  this.retryOpts.retry(
313
319
  err,
314
320
  {
315
- state: { counter: this.retryCount++, currentTimeout: this.retryAfter },
321
+ state: { counter: this.retryCount },
316
322
  opts: { retryOptions: this.retryOpts, ...this.opts }
317
323
  },
318
324
  onRetry.bind(this)
@@ -334,6 +340,7 @@ class RetryHandler {
334
340
  }
335
341
 
336
342
  try {
343
+ this.retryCountCheckpoint = this.retryCount
337
344
  this.dispatch(this.opts, this)
338
345
  } catch (err) {
339
346
  this.handler.onError(err)
@@ -157,12 +157,27 @@ class FormData {
157
157
  }
158
158
 
159
159
  [nodeUtil.inspect.custom] (depth, options) {
160
- let output = 'FormData:\n'
161
- this[kState].forEach(entry => {
162
- output += `${entry.name}: ${entry.value}\n`
163
- })
160
+ const state = this[kState].reduce((a, b) => {
161
+ if (a[b.name]) {
162
+ if (Array.isArray(a[b.name])) {
163
+ a[b.name].push(b.value)
164
+ } else {
165
+ a[b.name] = [a[b.name], b.value]
166
+ }
167
+ } else {
168
+ a[b.name] = b.value
169
+ }
170
+
171
+ return a
172
+ }, { __proto__: null })
173
+
174
+ options.depth ??= depth
175
+ options.colors ??= true
176
+
177
+ const output = nodeUtil.formatWithOptions(options, state)
164
178
 
165
- return output
179
+ // remove [Object null prototype]
180
+ return `FormData ${output.slice(output.indexOf(']') + 2)}`
166
181
  }
167
182
  }
168
183
 
@@ -572,16 +572,10 @@ class Headers {
572
572
  return (this[kHeadersList][kHeadersSortedMap] = headers)
573
573
  }
574
574
 
575
- [Symbol.for('nodejs.util.inspect.custom')] () {
576
- webidl.brandCheck(this, Headers)
577
-
578
- return this[kHeadersList]
579
- }
580
-
581
575
  [util.inspect.custom] (depth, options) {
582
- const inspected = util.inspect(this[kHeadersList].entries)
576
+ options.depth ??= depth
583
577
 
584
- return `Headers ${inspected}`
578
+ return `Headers ${util.formatWithOptions(options, this[kHeadersList].entries)}`
585
579
  }
586
580
  }
587
581
 
@@ -778,6 +778,8 @@ class Request {
778
778
  options.depth = 2
779
779
  }
780
780
 
781
+ options.colors ??= true
782
+
781
783
  const properties = {
782
784
  method: this.method,
783
785
  url: this.url,
@@ -796,7 +798,7 @@ class Request {
796
798
  signal: this.signal
797
799
  }
798
800
 
799
- return nodeUtil.formatWithOptions(options, { ...properties })
801
+ return `Request ${nodeUtil.formatWithOptions(options, properties)}`
800
802
  }
801
803
  }
802
804
 
@@ -259,6 +259,8 @@ class Response {
259
259
  options.depth = 2
260
260
  }
261
261
 
262
+ options.colors ??= true
263
+
262
264
  const properties = {
263
265
  status: this.status,
264
266
  statusText: this.statusText,
@@ -271,7 +273,7 @@ class Response {
271
273
  url: this.url
272
274
  }
273
275
 
274
- return nodeUtil.formatWithOptions(options, `Response ${nodeUtil.inspect(properties)}`)
276
+ return `Response ${nodeUtil.formatWithOptions(options, properties)}`
275
277
  }
276
278
  }
277
279
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "6.9.0",
3
+ "version": "6.10.1",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
@@ -0,0 +1,8 @@
1
+ 'use strict'
2
+
3
+ const { readFileSync, writeFileSync } = require('node:fs')
4
+ const { transcode } = require('node:buffer')
5
+
6
+ const buffer = transcode(readFileSync('./undici-fetch.js'), 'utf8', 'latin1')
7
+
8
+ writeFileSync('./undici-fetch.js', buffer.toString('latin1'))
@@ -18,6 +18,9 @@ declare class Dispatcher extends EventEmitter {
18
18
  /** Starts two-way communications with the requested resource. */
19
19
  connect(options: Dispatcher.ConnectOptions): Promise<Dispatcher.ConnectData>;
20
20
  connect(options: Dispatcher.ConnectOptions, callback: (err: Error | null, data: Dispatcher.ConnectData) => void): void;
21
+ /** Compose a chain of dispatchers */
22
+ compose(dispatchers: Dispatcher['dispatch'][]): Dispatcher.ComposedDispatcher;
23
+ compose(...dispatchers: Dispatcher['dispatch'][]): Dispatcher.ComposedDispatcher;
21
24
  /** Performs an HTTP request. */
22
25
  request(options: Dispatcher.RequestOptions): Promise<Dispatcher.ResponseData>;
23
26
  request(options: Dispatcher.RequestOptions, callback: (err: Error | null, data: Dispatcher.ResponseData) => void): void;
@@ -93,6 +96,8 @@ declare class Dispatcher extends EventEmitter {
93
96
  }
94
97
 
95
98
  declare namespace Dispatcher {
99
+ export interface ComposedDispatcher extends Dispatcher {}
100
+ export type DispatcherInterceptor = (dispatch: Dispatcher['dispatch']) => Dispatcher['dispatch'];
96
101
  export interface DispatchOptions {
97
102
  origin?: string | URL;
98
103
  path: string;
@@ -12,7 +12,7 @@ declare class RetryHandler implements Dispatcher.DispatchHandlers {
12
12
  }
13
13
 
14
14
  declare namespace RetryHandler {
15
- export type RetryState = { counter: number; currentTimeout: number };
15
+ export type RetryState = { counter: number; };
16
16
 
17
17
  export type RetryContext = {
18
18
  state: RetryState;