undici 7.0.0-alpha.1 → 7.0.0-alpha.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.
Files changed (83) hide show
  1. package/README.md +3 -3
  2. package/docs/docs/api/CacheStore.md +116 -0
  3. package/docs/docs/api/Client.md +1 -1
  4. package/docs/docs/api/Debug.md +1 -1
  5. package/docs/docs/api/Dispatcher.md +63 -2
  6. package/docs/docs/api/MockAgent.md +2 -0
  7. package/docs/docs/api/MockPool.md +2 -1
  8. package/docs/docs/api/RetryAgent.md +1 -1
  9. package/docs/docs/api/RetryHandler.md +1 -1
  10. package/docs/docs/api/WebSocket.md +45 -3
  11. package/index.js +11 -2
  12. package/lib/api/abort-signal.js +2 -0
  13. package/lib/api/api-pipeline.js +4 -2
  14. package/lib/api/api-request.js +5 -3
  15. package/lib/api/api-stream.js +3 -1
  16. package/lib/api/api-upgrade.js +2 -2
  17. package/lib/api/readable.js +200 -47
  18. package/lib/api/util.js +2 -0
  19. package/lib/cache/memory-cache-store.js +417 -0
  20. package/lib/core/connect.js +49 -22
  21. package/lib/core/constants.js +35 -10
  22. package/lib/core/diagnostics.js +122 -128
  23. package/lib/core/request.js +4 -4
  24. package/lib/core/symbols.js +2 -0
  25. package/lib/core/tree.js +4 -2
  26. package/lib/core/util.js +261 -41
  27. package/lib/dispatcher/client-h1.js +394 -142
  28. package/lib/dispatcher/client-h2.js +128 -76
  29. package/lib/dispatcher/client.js +24 -7
  30. package/lib/dispatcher/fixed-queue.js +91 -49
  31. package/lib/dispatcher/pool-base.js +3 -3
  32. package/lib/dispatcher/pool-stats.js +2 -0
  33. package/lib/dispatcher/proxy-agent.js +3 -1
  34. package/lib/handler/cache-handler.js +359 -0
  35. package/lib/handler/cache-revalidation-handler.js +119 -0
  36. package/lib/handler/redirect-handler.js +2 -2
  37. package/lib/handler/retry-handler.js +2 -2
  38. package/lib/interceptor/cache.js +171 -0
  39. package/lib/interceptor/dns.js +346 -0
  40. package/lib/mock/mock-agent.js +5 -8
  41. package/lib/mock/mock-client.js +7 -2
  42. package/lib/mock/mock-errors.js +3 -1
  43. package/lib/mock/mock-interceptor.js +8 -6
  44. package/lib/mock/mock-pool.js +7 -2
  45. package/lib/mock/mock-symbols.js +2 -1
  46. package/lib/mock/mock-utils.js +33 -5
  47. package/lib/util/cache.js +224 -0
  48. package/lib/util/timers.js +50 -6
  49. package/lib/web/cache/cache.js +25 -21
  50. package/lib/web/cache/cachestorage.js +3 -1
  51. package/lib/web/cookies/index.js +6 -4
  52. package/lib/web/eventsource/eventsource.js +2 -0
  53. package/lib/web/fetch/body.js +42 -34
  54. package/lib/web/fetch/constants.js +45 -29
  55. package/lib/web/fetch/data-url.js +2 -2
  56. package/lib/web/fetch/formdata-parser.js +14 -3
  57. package/lib/web/fetch/formdata.js +42 -20
  58. package/lib/web/fetch/headers.js +118 -84
  59. package/lib/web/fetch/index.js +65 -59
  60. package/lib/web/fetch/request.js +132 -55
  61. package/lib/web/fetch/response.js +81 -36
  62. package/lib/web/fetch/util.js +274 -103
  63. package/lib/web/fetch/webidl.js +42 -14
  64. package/lib/web/websocket/connection.js +92 -15
  65. package/lib/web/websocket/constants.js +69 -9
  66. package/lib/web/websocket/events.js +8 -2
  67. package/lib/web/websocket/receiver.js +20 -26
  68. package/lib/web/websocket/stream/websocketerror.js +83 -0
  69. package/lib/web/websocket/stream/websocketstream.js +485 -0
  70. package/lib/web/websocket/util.js +115 -10
  71. package/lib/web/websocket/websocket.js +47 -170
  72. package/package.json +12 -8
  73. package/types/cache-interceptor.d.ts +97 -0
  74. package/types/fetch.d.ts +9 -8
  75. package/types/index.d.ts +3 -0
  76. package/types/interceptors.d.ts +18 -0
  77. package/types/mock-agent.d.ts +3 -0
  78. package/types/readable.d.ts +10 -7
  79. package/types/webidl.d.ts +30 -4
  80. package/types/websocket.d.ts +33 -0
  81. package/lib/mock/pluralizer.js +0 -29
  82. package/lib/web/cache/symbols.js +0 -5
  83. package/lib/web/fetch/symbols.js +0 -8
package/README.md CHANGED
@@ -132,7 +132,7 @@ Returns a promise with the result of the `Dispatcher.request` method.
132
132
 
133
133
  Calls `options.dispatcher.request(options)`.
134
134
 
135
- See [Dispatcher.request](./docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback) for more details, and [request examples](./examples/README.md) for examples.
135
+ See [Dispatcher.request](./docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback) for more details, and [request examples](./docs/examples/README.md) for examples.
136
136
 
137
137
  ### `undici.stream([url, options, ]factory): Promise`
138
138
 
@@ -230,7 +230,7 @@ A body can be of the following types:
230
230
  - URLSearchParams
231
231
  - FormData
232
232
 
233
- In this implementation of fetch, ```request.body``` now accepts ```Async Iterables```. It is not present in the [Fetch Standard.](https://fetch.spec.whatwg.org)
233
+ In this implementation of fetch, ```request.body``` now accepts ```Async Iterables```. It is not present in the [Fetch Standard](https://fetch.spec.whatwg.org).
234
234
 
235
235
  ```js
236
236
  import { fetch } from 'undici'
@@ -261,7 +261,7 @@ await fetch('http://example.com', { method: 'POST', body })
261
261
 
262
262
  - `'half'`
263
263
 
264
- In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`, however, even though the value must be set to `'half'`, it is actually a _full_ duplex. For more detail refer to the [Fetch Standard.](https://fetch.spec.whatwg.org/#dom-requestinit-duplex).
264
+ In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`, however, even though the value must be set to `'half'`, it is actually a _full_ duplex. For more detail refer to the [Fetch Standard](https://fetch.spec.whatwg.org/#dom-requestinit-duplex).
265
265
 
266
266
  #### `response.body`
267
267
 
@@ -0,0 +1,116 @@
1
+ # Cache Store
2
+
3
+ A Cache Store is responsible for storing and retrieving cached responses.
4
+ It is also responsible for deciding which specific response to use based off of
5
+ a response's `Vary` header (if present).
6
+
7
+ ## Pre-built Cache Stores
8
+
9
+ ### `MemoryCacheStore`
10
+
11
+ The `MemoryCacheStore` stores the responses in-memory.
12
+
13
+ **Options**
14
+
15
+ - `maxEntries` - The maximum amount of responses to store. Default `Infinity`.
16
+ - `maxEntrySize` - The maximum size in bytes that a response's body can be. If a response's body is greater than or equal to this, the response will not be cached.
17
+
18
+ ## Defining a Custom Cache Store
19
+
20
+ The store must implement the following functions:
21
+
22
+ ### Getter: `isFull`
23
+
24
+ This tells the cache interceptor if the store is full or not. If this is true,
25
+ the cache interceptor will not attempt to cache the response.
26
+
27
+ ### Function: `createReadStream`
28
+
29
+ Parameters:
30
+
31
+ * **req** `Dispatcher.RequestOptions` - Incoming request
32
+
33
+ Returns: `CacheStoreReadable | Promise<CacheStoreReadable | undefined> | undefined` - If the request is cached, a readable for the body is returned. Otherwise, `undefined` is returned.
34
+
35
+ ### Function: `createWriteStream`
36
+
37
+ Parameters:
38
+
39
+ * **req** `Dispatcher.RequestOptions` - Incoming request
40
+ * **value** `CacheStoreValue` - Response to store
41
+
42
+ Returns: `CacheStoreWriteable | undefined` - If the store is full, return `undefined`. Otherwise, return a writable so that the cache interceptor can stream the body and trailers to the store.
43
+
44
+ ## `CacheStoreValue`
45
+
46
+ This is an interface containing the majority of a response's data (minus the body).
47
+
48
+ ### Property `statusCode`
49
+
50
+ `number` - The response's HTTP status code.
51
+
52
+ ### Property `statusMessage`
53
+
54
+ `string` - The response's HTTP status message.
55
+
56
+ ### Property `rawHeaders`
57
+
58
+ `(Buffer | Buffer[])[]` - The response's headers.
59
+
60
+ ### Property `rawTrailers`
61
+
62
+ `string[] | undefined` - The response's trailers.
63
+
64
+ ### Property `vary`
65
+
66
+ `Record<string, string> | undefined` - The headers defined by the response's `Vary` header
67
+ and their respective values for later comparison
68
+
69
+ For example, for a response like
70
+ ```
71
+ Vary: content-encoding, accepts
72
+ content-encoding: utf8
73
+ accepts: application/json
74
+ ```
75
+
76
+ This would be
77
+ ```js
78
+ {
79
+ 'content-encoding': 'utf8',
80
+ accepts: 'application/json'
81
+ }
82
+ ```
83
+
84
+ ### Property `cachedAt`
85
+
86
+ `number` - Time in millis that this value was cached.
87
+
88
+ ### Property `staleAt`
89
+
90
+ `number` - Time in millis that this value is considered stale.
91
+
92
+ ### Property `deleteAt`
93
+
94
+ `number` - Time in millis that this value is to be deleted from the cache. This
95
+ is either the same sa staleAt or the `max-stale` caching directive.
96
+
97
+ The store must not return a response after the time defined in this property.
98
+
99
+ ## `CacheStoreReadable`
100
+
101
+ This extends Node's [`Readable`](https://nodejs.org/api/stream.html#class-streamreadable)
102
+ and defines extra properties relevant to the cache interceptor.
103
+
104
+ ### Getter: `value`
105
+
106
+ The response's [`CacheStoreValue`](#cachestorevalue)
107
+
108
+ ## `CacheStoreWriteable`
109
+
110
+ This extends Node's [`Writable`](https://nodejs.org/api/stream.html#class-streamwritable)
111
+ and defines extra properties relevant to the cache interceptor.
112
+
113
+ ### Setter: `rawTrailers`
114
+
115
+ If the response has trailers, the cache interceptor will pass them to the cache
116
+ interceptor through this method.
@@ -19,7 +19,7 @@ Returns: `Client`
19
19
 
20
20
  > ⚠️ Warning: The `H2` support is experimental.
21
21
 
22
- * **bodyTimeout** `number | null` (optional) - Default: `300e3` - 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 300 seconds. Please note the `timeout` will be reset if you keep writing data to the scoket everytime.
22
+ * **bodyTimeout** `number | null` (optional) - Default: `300e3` - 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 300 seconds. Please note the `timeout` will be reset if you keep writing data to the socket everytime.
23
23
  * **headersTimeout** `number | null` (optional) - Default: `300e3` - The amount of time, in milliseconds, the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds.
24
24
  * **keepAliveMaxTimeout** `number | null` (optional) - Default: `600e3` - The maximum allowed `keepAliveTimeout`, in milliseconds, when overridden by *keep-alive* hints from the server. Defaults to 10 minutes.
25
25
  * **keepAliveTimeout** `number | null` (optional) - Default: `4e3` - The timeout, in milliseconds, after which a socket without active requests will time out. Monitors time between activity on a connected socket. This value may be overridden by *keep-alive* hints from the server. See [MDN: HTTP - Headers - Keep-Alive directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive#directives) for more details. Defaults to 4 seconds.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Undici (and subsenquently `fetch` and `websocket`) exposes a debug statement that can be enabled by setting `NODE_DEBUG` within the environment.
4
4
 
5
- The flags availabile are:
5
+ The flags available are:
6
6
 
7
7
  ## `undici`
8
8
 
@@ -478,7 +478,7 @@ The `RequestOptions.method` property should not be value `'CONNECT'`.
478
478
  #### Parameter: `ResponseData`
479
479
 
480
480
  * **statusCode** `number`
481
- * **headers** `Record<string, string | string[]>` - Note that all header keys are lower-cased, e. g. `content-type`.
481
+ * **headers** `Record<string, string | string[]>` - Note that all header keys are lower-cased, e.g. `content-type`.
482
482
  * **body** `stream.Readable` which also implements [the body mixin from the Fetch Standard](https://fetch.spec.whatwg.org/#body-mixin).
483
483
  * **trailers** `Record<string, string>` - This object starts out
484
484
  as empty and will be mutated to contain trailers after `body` has emitted `'end'`.
@@ -974,7 +974,7 @@ const client = new Client("http://example.com").compose(
974
974
  })
975
975
  );
976
976
 
977
- // or
977
+ // or
978
978
  client.dispatch(
979
979
  {
980
980
  path: "/",
@@ -985,6 +985,57 @@ client.dispatch(
985
985
  );
986
986
  ```
987
987
 
988
+ ##### `dns`
989
+
990
+ The `dns` interceptor enables you to cache DNS lookups for a given duration, per origin.
991
+
992
+ >It is well suited for scenarios where you want to cache DNS lookups to avoid the overhead of resolving the same domain multiple times
993
+
994
+ **Options**
995
+ - `maxTTL` - The maximum time-to-live (in milliseconds) of the DNS cache. It should be a positive integer. Default: `10000`.
996
+ - Set `0` to disable TTL.
997
+ - `maxItems` - The maximum number of items to cache. It should be a positive integer. Default: `Infinity`.
998
+ - `dualStack` - Whether to resolve both IPv4 and IPv6 addresses. Default: `true`.
999
+ - It will also attempt a happy-eyeballs-like approach to connect to the available addresses in case of a connection failure.
1000
+ - `affinity` - Whether to use IPv4 or IPv6 addresses. Default: `4`.
1001
+ - It can be either `'4` or `6`.
1002
+ - It will only take effect if `dualStack` is `false`.
1003
+ - `lookup: (hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException | null, addresses: DNSInterceptorRecord[]) => void) => void` - Custom lookup function. Default: `dns.lookup`.
1004
+ - For more info see [dns.lookup](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback).
1005
+ - `pick: (origin: URL, records: DNSInterceptorRecords, affinity: 4 | 6) => DNSInterceptorRecord` - Custom pick function. Default: `RoundRobin`.
1006
+ - The function should return a single record from the records array.
1007
+ - By default a simplified version of Round Robin is used.
1008
+ - The `records` property can be mutated to store the state of the balancing algorithm.
1009
+
1010
+ > The `Dispatcher#options` also gets extended with the options `dns.affinity`, `dns.dualStack`, `dns.lookup` and `dns.pick` which can be used to configure the interceptor at a request-per-request basis.
1011
+
1012
+
1013
+ **DNSInterceptorRecord**
1014
+ It represents a DNS record.
1015
+ - `family` - (`number`) The IP family of the address. It can be either `4` or `6`.
1016
+ - `address` - (`string`) The IP address.
1017
+
1018
+ **DNSInterceptorOriginRecords**
1019
+ It represents a map of DNS IP addresses records for a single origin.
1020
+ - `4.ips` - (`DNSInterceptorRecord[] | null`) The IPv4 addresses.
1021
+ - `6.ips` - (`DNSInterceptorRecord[] | null`) The IPv6 addresses.
1022
+
1023
+ **Example - Basic DNS Interceptor**
1024
+
1025
+ ```js
1026
+ const { Client, interceptors } = require("undici");
1027
+ const { dns } = interceptors;
1028
+
1029
+ const client = new Agent().compose([
1030
+ dns({ ...opts })
1031
+ ])
1032
+
1033
+ const response = await client.request({
1034
+ origin: `http://localhost:3030`,
1035
+ ...requestOpts
1036
+ })
1037
+ ```
1038
+
988
1039
  ##### `Response Error Interceptor`
989
1040
 
990
1041
  **Introduction**
@@ -1182,6 +1233,16 @@ test('should not error if request status code is not in the specified error code
1182
1233
 
1183
1234
  The Response Error Interceptor provides a robust mechanism for handling HTTP response errors by capturing detailed error information and propagating it through a structured `ResponseError` class. This enhancement improves error handling and debugging capabilities in applications using the interceptor.
1184
1235
 
1236
+ ##### `Cache Interceptor`
1237
+
1238
+ The `cache` interceptor implements client-side response caching as described in
1239
+ [RFC9111](https://www.rfc-editor.org/rfc/rfc9111.html).
1240
+
1241
+ **Options**
1242
+
1243
+ - `store` - The [`CacheStore`](./CacheStore.md) to store and retrieve responses from. Default is [`MemoryCacheStore`](./CacheStore.md#memorycachestore).
1244
+ - `methods` - The [**safe** HTTP methods](https://www.rfc-editor.org/rfc/rfc9110#section-9.2.1) to cache the response of.
1245
+
1185
1246
  ## Instance Events
1186
1247
 
1187
1248
  ### Event: `'connect'`
@@ -18,6 +18,8 @@ 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
 
21
+ * **ignoreTrailingSlash** `boolean` (optional) - Default: `false` - set the default value for `ignoreTrailingSlash` for interceptors.
22
+
21
23
  ### Example - Basic MockAgent instantiation
22
24
 
23
25
  This will instantiate the MockAgent. It will not do anything until registered as the agent to use with requests and mock interceptions are added.
@@ -58,6 +58,7 @@ Returns: `MockInterceptor` corresponding to the input options.
58
58
  * **body** `string | RegExp | (body: string) => boolean` - (optional) - a matcher for the HTTP request body.
59
59
  * **headers** `Record<string, string | RegExp | (body: string) => boolean`> - (optional) - a matcher for the HTTP request headers. To be intercepted, a request must match all defined headers. Extra headers not defined here may (or may not) be included in the request and do not affect the interception in any way.
60
60
  * **query** `Record<string, any> | null` - (optional) - a matcher for the HTTP request query string params. Only applies when a `string` was provided for `MockPoolInterceptOptions.path`.
61
+ * **ignoreTrailingSlash** `boolean` - (optional) - set to `true` if the matcher should also match by ignoring potential trailing slashes in `MockPoolInterceptOptions.path`.
61
62
 
62
63
  ### Return: `MockInterceptor`
63
64
 
@@ -81,7 +82,7 @@ By default, `reply` and `replyWithError` define the behaviour for the first matc
81
82
 
82
83
  ### Return: `MockScope`
83
84
 
84
- A `MockScope` is associated with a single `MockInterceptor`. With this, we can configure the default behaviour of a intercepted reply.
85
+ A `MockScope` is associated with a single `MockInterceptor`. With this, we can configure the default behaviour of an intercepted reply.
85
86
 
86
87
  * **delay** `(waitInMs: number) => MockScope` - delay the associated reply by a set amount in ms.
87
88
  * **persist** `() => MockScope` - any matching request will always reply with the defined response indefinitely.
@@ -40,6 +40,6 @@ import { Agent, RetryAgent } from 'undici'
40
40
  const agent = new RetryAgent(new Agent())
41
41
 
42
42
  const res = await agent.request('http://example.com')
43
- console.log(res.statuCode)
43
+ console.log(res.statusCode)
44
44
  console.log(await res.body.text())
45
45
  ```
@@ -46,7 +46,7 @@ It represents the retry state for a given request.
46
46
  - **dispatch** `(options: Dispatch.DispatchOptions, handlers: Dispatch.DispatchHandlers) => Promise<Dispatch.DispatchResponse>` (required) - Dispatch function to be called after every retry.
47
47
  - **handler** Extends [`Dispatch.DispatchHandlers`](Dispatcher.md#dispatcherdispatchoptions-handler) (required) - Handler function to be called after the request is successful or the retries are exhausted.
48
48
 
49
- >__Note__: The `RetryHandler` does not retry over stateful bodies (e.g. streams, AsyncIterable) as those, once consumed, are left in an state that cannot be reutilized. For these situations the `RetryHandler` will identify
49
+ >__Note__: The `RetryHandler` does not retry over stateful bodies (e.g. streams, AsyncIterable) as those, once consumed, are left in a state that cannot be reutilized. For these situations the `RetryHandler` will identify
50
50
  >the body as stateful and will not retry the request rejecting with the error `UND_ERR_REQ_RETRY`.
51
51
 
52
52
  Examples:
@@ -1,7 +1,5 @@
1
1
  # Class: WebSocket
2
2
 
3
- > ⚠️ Warning: the WebSocket API is experimental.
4
-
5
3
  Extends: [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
6
4
 
7
5
  The WebSocket object provides a way to manage a WebSocket connection to a server, allowing bidirectional communication. The API follows the [WebSocket spec](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) and [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455).
@@ -10,7 +8,7 @@ The WebSocket object provides a way to manage a WebSocket connection to a server
10
8
 
11
9
  Arguments:
12
10
 
13
- * **url** `URL | string` - The url's protocol *must* be `ws` or `wss`.
11
+ * **url** `URL | string`
14
12
  * **protocol** `string | string[] | WebSocketInit` (optional) - Subprotocol(s) to request the server use, or a [`Dispatcher`](./Dispatcher.md).
15
13
 
16
14
  ### Example:
@@ -36,6 +34,50 @@ import { WebSocket } from 'undici'
36
34
  const ws = new WebSocket('wss://echo.websocket.events', ['echo', 'chat'])
37
35
  ```
38
36
 
37
+ # Class: WebSocketStream
38
+
39
+ > ⚠️ Warning: the WebSocketStream API has not been finalized and is likely to change.
40
+
41
+ See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocketStream) for more information.
42
+
43
+ ## `new WebSocketStream(url[, protocol])`
44
+
45
+ Arguments:
46
+
47
+ * **url** `URL | string`
48
+ * **options** `WebSocketStreamOptions` (optional)
49
+
50
+ ### WebSocketStream Example
51
+
52
+ ```js
53
+ const stream = new WebSocketStream('https://echo.websocket.org/')
54
+ const { readable, writable } = await stream.opened
55
+
56
+ async function read () {
57
+ /** @type {ReadableStreamReader} */
58
+ const reader = readable.getReader()
59
+
60
+ while (true) {
61
+ const { done, value } = await reader.read()
62
+ if (done) break
63
+
64
+ // do something with value
65
+ }
66
+ }
67
+
68
+ async function write () {
69
+ /** @type {WritableStreamDefaultWriter} */
70
+ const writer = writable.getWriter()
71
+ writer.write('Hello, world!')
72
+ writer.releaseLock()
73
+ }
74
+
75
+ read()
76
+
77
+ setInterval(() => write(), 5000)
78
+
79
+ ```
80
+
39
81
  ## Read More
40
82
 
41
83
  - [MDN - WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
package/index.js CHANGED
@@ -39,7 +39,13 @@ module.exports.RedirectHandler = RedirectHandler
39
39
  module.exports.interceptors = {
40
40
  redirect: require('./lib/interceptor/redirect'),
41
41
  retry: require('./lib/interceptor/retry'),
42
- dump: require('./lib/interceptor/dump')
42
+ dump: require('./lib/interceptor/dump'),
43
+ dns: require('./lib/interceptor/dns'),
44
+ cache: require('./lib/interceptor/cache')
45
+ }
46
+
47
+ module.exports.cacheStores = {
48
+ MemoryCacheStore: require('./lib/cache/memory-cache-store')
43
49
  }
44
50
 
45
51
  module.exports.buildConnector = buildConnector
@@ -124,7 +130,7 @@ module.exports.setGlobalOrigin = setGlobalOrigin
124
130
  module.exports.getGlobalOrigin = getGlobalOrigin
125
131
 
126
132
  const { CacheStorage } = require('./lib/web/cache/cachestorage')
127
- const { kConstruct } = require('./lib/web/cache/symbols')
133
+ const { kConstruct } = require('./lib/core/symbols')
128
134
 
129
135
  // Cache & CacheStorage are tightly coupled with fetch. Even if it may run
130
136
  // in an older version of Node, it doesn't have any use without fetch.
@@ -148,6 +154,9 @@ module.exports.CloseEvent = CloseEvent
148
154
  module.exports.ErrorEvent = ErrorEvent
149
155
  module.exports.MessageEvent = MessageEvent
150
156
 
157
+ module.exports.WebSocketStream = require('./lib/web/websocket/stream/websocketstream').WebSocketStream
158
+ module.exports.WebSocketError = require('./lib/web/websocket/stream/websocketerror').WebSocketError
159
+
151
160
  module.exports.request = makeDispatcher(api.request)
152
161
  module.exports.stream = makeDispatcher(api.stream)
153
162
  module.exports.pipeline = makeDispatcher(api.pipeline)
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { addAbortListener } = require('../core/util')
2
4
  const { RequestAbortedError } = require('../core/errors')
3
5
 
@@ -15,6 +15,8 @@ const {
15
15
  const util = require('../core/util')
16
16
  const { addSignal, removeSignal } = require('./abort-signal')
17
17
 
18
+ function noop () {}
19
+
18
20
  const kResume = Symbol('resume')
19
21
 
20
22
  class PipelineRequest extends Readable {
@@ -92,7 +94,7 @@ class PipelineHandler extends AsyncResource {
92
94
  this.context = null
93
95
  this.onInfo = onInfo || null
94
96
 
95
- this.req = new PipelineRequest().on('error', util.nop)
97
+ this.req = new PipelineRequest().on('error', noop)
96
98
 
97
99
  this.ret = new Duplex({
98
100
  readableObjectMode: opts.objectMode,
@@ -183,7 +185,7 @@ class PipelineHandler extends AsyncResource {
183
185
  context
184
186
  })
185
187
  } catch (err) {
186
- this.res.on('error', util.nop)
188
+ this.res.on('error', noop)
187
189
  throw err
188
190
  }
189
191
 
@@ -6,6 +6,8 @@ const { Readable } = require('./readable')
6
6
  const { InvalidArgumentError, RequestAbortedError } = require('../core/errors')
7
7
  const util = require('../core/util')
8
8
 
9
+ function noop () {}
10
+
9
11
  class RequestHandler extends AsyncResource {
10
12
  constructor (opts, callback) {
11
13
  if (!opts || typeof opts !== 'object') {
@@ -38,7 +40,7 @@ class RequestHandler extends AsyncResource {
38
40
  super('UNDICI_REQUEST')
39
41
  } catch (err) {
40
42
  if (util.isStream(body)) {
41
- util.destroy(body.on('error', util.nop), err)
43
+ util.destroy(body.on('error', noop), err)
42
44
  }
43
45
  throw err
44
46
  }
@@ -63,7 +65,7 @@ class RequestHandler extends AsyncResource {
63
65
  this.removeAbortListener = util.addAbortListener(signal, () => {
64
66
  this.reason = signal.reason ?? new RequestAbortedError()
65
67
  if (this.res) {
66
- util.destroy(this.res, this.reason)
68
+ util.destroy(this.res.on('error', noop), this.reason)
67
69
  } else if (this.abort) {
68
70
  this.abort(this.reason)
69
71
  }
@@ -159,7 +161,7 @@ class RequestHandler extends AsyncResource {
159
161
  this.body = null
160
162
 
161
163
  if (util.isStream(body)) {
162
- body.on('error', util.nop)
164
+ body.on('error', noop)
163
165
  util.destroy(body, err)
164
166
  }
165
167
  }
@@ -7,6 +7,8 @@ const { InvalidArgumentError, InvalidReturnValueError } = require('../core/error
7
7
  const util = require('../core/util')
8
8
  const { addSignal, removeSignal } = require('./abort-signal')
9
9
 
10
+ function noop () {}
11
+
10
12
  class StreamHandler extends AsyncResource {
11
13
  constructor (opts, factory, callback) {
12
14
  if (!opts || typeof opts !== 'object') {
@@ -39,7 +41,7 @@ class StreamHandler extends AsyncResource {
39
41
  super('UNDICI_STREAM')
40
42
  } catch (err) {
41
43
  if (util.isStream(body)) {
42
- util.destroy(body.on('error', util.nop), err)
44
+ util.destroy(body.on('error', noop), err)
43
45
  }
44
46
  throw err
45
47
  }
@@ -50,9 +50,9 @@ class UpgradeHandler extends AsyncResource {
50
50
  }
51
51
 
52
52
  onUpgrade (statusCode, rawHeaders, socket) {
53
- const { callback, opaque, context } = this
53
+ assert(statusCode === 101)
54
54
 
55
- assert.strictEqual(statusCode, 101)
55
+ const { callback, opaque, context } = this
56
56
 
57
57
  removeSignal(this)
58
58