deepv-code 1.0.182 → 1.0.185
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/bundle/dvcode.js +757 -753
- package/package.json +1 -1
- package/bundle/assets/help/README.md +0 -113
- package/bundle/assets/sounds/README.md +0 -74
- package/bundle/node_modules/undici/LICENSE +0 -21
- package/bundle/node_modules/undici/README.md +0 -472
- package/bundle/node_modules/undici/docs/docs/api/Agent.md +0 -83
- package/bundle/node_modules/undici/docs/docs/api/BalancedPool.md +0 -99
- package/bundle/node_modules/undici/docs/docs/api/CacheStorage.md +0 -30
- package/bundle/node_modules/undici/docs/docs/api/CacheStore.md +0 -151
- package/bundle/node_modules/undici/docs/docs/api/Client.md +0 -281
- package/bundle/node_modules/undici/docs/docs/api/ClientStats.md +0 -27
- package/bundle/node_modules/undici/docs/docs/api/Connector.md +0 -115
- package/bundle/node_modules/undici/docs/docs/api/ContentType.md +0 -57
- package/bundle/node_modules/undici/docs/docs/api/Cookies.md +0 -101
- package/bundle/node_modules/undici/docs/docs/api/Debug.md +0 -62
- package/bundle/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +0 -204
- package/bundle/node_modules/undici/docs/docs/api/Dispatcher.md +0 -1200
- package/bundle/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +0 -159
- package/bundle/node_modules/undici/docs/docs/api/Errors.md +0 -49
- package/bundle/node_modules/undici/docs/docs/api/EventSource.md +0 -45
- package/bundle/node_modules/undici/docs/docs/api/Fetch.md +0 -52
- package/bundle/node_modules/undici/docs/docs/api/H2CClient.md +0 -262
- package/bundle/node_modules/undici/docs/docs/api/MockAgent.md +0 -603
- package/bundle/node_modules/undici/docs/docs/api/MockCallHistory.md +0 -197
- package/bundle/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +0 -43
- package/bundle/node_modules/undici/docs/docs/api/MockClient.md +0 -77
- package/bundle/node_modules/undici/docs/docs/api/MockErrors.md +0 -12
- package/bundle/node_modules/undici/docs/docs/api/MockPool.md +0 -548
- package/bundle/node_modules/undici/docs/docs/api/Pool.md +0 -84
- package/bundle/node_modules/undici/docs/docs/api/PoolStats.md +0 -35
- package/bundle/node_modules/undici/docs/docs/api/ProxyAgent.md +0 -227
- package/bundle/node_modules/undici/docs/docs/api/RedirectHandler.md +0 -96
- package/bundle/node_modules/undici/docs/docs/api/RetryAgent.md +0 -45
- package/bundle/node_modules/undici/docs/docs/api/RetryHandler.md +0 -117
- package/bundle/node_modules/undici/docs/docs/api/Util.md +0 -25
- package/bundle/node_modules/undici/docs/docs/api/WebSocket.md +0 -85
- package/bundle/node_modules/undici/docs/docs/api/api-lifecycle.md +0 -91
- package/bundle/node_modules/undici/docs/docs/best-practices/client-certificate.md +0 -64
- package/bundle/node_modules/undici/docs/docs/best-practices/mocking-request.md +0 -190
- package/bundle/node_modules/undici/docs/docs/best-practices/proxy.md +0 -127
- package/bundle/node_modules/undici/docs/docs/best-practices/writing-tests.md +0 -20
- package/bundle/node_modules/undici/index-fetch.js +0 -35
- package/bundle/node_modules/undici/index.d.ts +0 -3
- package/bundle/node_modules/undici/index.js +0 -183
- package/bundle/node_modules/undici/lib/api/abort-signal.js +0 -59
- package/bundle/node_modules/undici/lib/api/api-connect.js +0 -110
- package/bundle/node_modules/undici/lib/api/api-pipeline.js +0 -252
- package/bundle/node_modules/undici/lib/api/api-request.js +0 -199
- package/bundle/node_modules/undici/lib/api/api-stream.js +0 -209
- package/bundle/node_modules/undici/lib/api/api-upgrade.js +0 -110
- package/bundle/node_modules/undici/lib/api/index.js +0 -7
- package/bundle/node_modules/undici/lib/api/readable.js +0 -558
- package/bundle/node_modules/undici/lib/api/util.js +0 -95
- package/bundle/node_modules/undici/lib/cache/memory-cache-store.js +0 -234
- package/bundle/node_modules/undici/lib/cache/sqlite-cache-store.js +0 -461
- package/bundle/node_modules/undici/lib/core/connect.js +0 -164
- package/bundle/node_modules/undici/lib/core/constants.js +0 -143
- package/bundle/node_modules/undici/lib/core/diagnostics.js +0 -196
- package/bundle/node_modules/undici/lib/core/errors.js +0 -244
- package/bundle/node_modules/undici/lib/core/request.js +0 -397
- package/bundle/node_modules/undici/lib/core/symbols.js +0 -68
- package/bundle/node_modules/undici/lib/core/tree.js +0 -160
- package/bundle/node_modules/undici/lib/core/util.js +0 -988
- package/bundle/node_modules/undici/lib/dispatcher/agent.js +0 -135
- package/bundle/node_modules/undici/lib/dispatcher/balanced-pool.js +0 -206
- package/bundle/node_modules/undici/lib/dispatcher/client-h1.js +0 -1615
- package/bundle/node_modules/undici/lib/dispatcher/client-h2.js +0 -798
- package/bundle/node_modules/undici/lib/dispatcher/client.js +0 -614
- package/bundle/node_modules/undici/lib/dispatcher/dispatcher-base.js +0 -161
- package/bundle/node_modules/undici/lib/dispatcher/dispatcher.js +0 -48
- package/bundle/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +0 -151
- package/bundle/node_modules/undici/lib/dispatcher/fixed-queue.js +0 -159
- package/bundle/node_modules/undici/lib/dispatcher/h2c-client.js +0 -122
- package/bundle/node_modules/undici/lib/dispatcher/pool-base.js +0 -191
- package/bundle/node_modules/undici/lib/dispatcher/pool.js +0 -118
- package/bundle/node_modules/undici/lib/dispatcher/proxy-agent.js +0 -275
- package/bundle/node_modules/undici/lib/dispatcher/retry-agent.js +0 -35
- package/bundle/node_modules/undici/lib/global.js +0 -32
- package/bundle/node_modules/undici/lib/handler/cache-handler.js +0 -448
- package/bundle/node_modules/undici/lib/handler/cache-revalidation-handler.js +0 -124
- package/bundle/node_modules/undici/lib/handler/decorator-handler.js +0 -67
- package/bundle/node_modules/undici/lib/handler/redirect-handler.js +0 -227
- package/bundle/node_modules/undici/lib/handler/retry-handler.js +0 -342
- package/bundle/node_modules/undici/lib/handler/unwrap-handler.js +0 -96
- package/bundle/node_modules/undici/lib/handler/wrap-handler.js +0 -95
- package/bundle/node_modules/undici/lib/interceptor/cache.js +0 -372
- package/bundle/node_modules/undici/lib/interceptor/dns.js +0 -432
- package/bundle/node_modules/undici/lib/interceptor/dump.js +0 -111
- package/bundle/node_modules/undici/lib/interceptor/redirect.js +0 -21
- package/bundle/node_modules/undici/lib/interceptor/response-error.js +0 -95
- package/bundle/node_modules/undici/lib/interceptor/retry.js +0 -19
- package/bundle/node_modules/undici/lib/llhttp/.gitkeep +0 -0
- package/bundle/node_modules/undici/lib/llhttp/constants.d.ts +0 -97
- package/bundle/node_modules/undici/lib/llhttp/constants.js +0 -498
- package/bundle/node_modules/undici/lib/llhttp/constants.js.map +0 -1
- package/bundle/node_modules/undici/lib/llhttp/llhttp-wasm.js +0 -15
- package/bundle/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +0 -15
- package/bundle/node_modules/undici/lib/llhttp/utils.d.ts +0 -2
- package/bundle/node_modules/undici/lib/llhttp/utils.js +0 -15
- package/bundle/node_modules/undici/lib/llhttp/utils.js.map +0 -1
- package/bundle/node_modules/undici/lib/mock/mock-agent.js +0 -224
- package/bundle/node_modules/undici/lib/mock/mock-call-history.js +0 -248
- package/bundle/node_modules/undici/lib/mock/mock-client.js +0 -64
- package/bundle/node_modules/undici/lib/mock/mock-errors.js +0 -19
- package/bundle/node_modules/undici/lib/mock/mock-interceptor.js +0 -209
- package/bundle/node_modules/undici/lib/mock/mock-pool.js +0 -64
- package/bundle/node_modules/undici/lib/mock/mock-symbols.js +0 -31
- package/bundle/node_modules/undici/lib/mock/mock-utils.js +0 -433
- package/bundle/node_modules/undici/lib/mock/pending-interceptors-formatter.js +0 -43
- package/bundle/node_modules/undici/lib/util/cache.js +0 -368
- package/bundle/node_modules/undici/lib/util/date.js +0 -259
- package/bundle/node_modules/undici/lib/util/stats.js +0 -32
- package/bundle/node_modules/undici/lib/util/timers.js +0 -423
- package/bundle/node_modules/undici/lib/web/cache/cache.js +0 -862
- package/bundle/node_modules/undici/lib/web/cache/cachestorage.js +0 -152
- package/bundle/node_modules/undici/lib/web/cache/util.js +0 -45
- package/bundle/node_modules/undici/lib/web/cookies/constants.js +0 -12
- package/bundle/node_modules/undici/lib/web/cookies/index.js +0 -199
- package/bundle/node_modules/undici/lib/web/cookies/parse.js +0 -322
- package/bundle/node_modules/undici/lib/web/cookies/util.js +0 -282
- package/bundle/node_modules/undici/lib/web/eventsource/eventsource-stream.js +0 -399
- package/bundle/node_modules/undici/lib/web/eventsource/eventsource.js +0 -484
- package/bundle/node_modules/undici/lib/web/eventsource/util.js +0 -37
- package/bundle/node_modules/undici/lib/web/fetch/LICENSE +0 -21
- package/bundle/node_modules/undici/lib/web/fetch/body.js +0 -532
- package/bundle/node_modules/undici/lib/web/fetch/constants.js +0 -131
- package/bundle/node_modules/undici/lib/web/fetch/data-url.js +0 -744
- package/bundle/node_modules/undici/lib/web/fetch/dispatcher-weakref.js +0 -46
- package/bundle/node_modules/undici/lib/web/fetch/formdata-parser.js +0 -501
- package/bundle/node_modules/undici/lib/web/fetch/formdata.js +0 -263
- package/bundle/node_modules/undici/lib/web/fetch/global.js +0 -40
- package/bundle/node_modules/undici/lib/web/fetch/headers.js +0 -719
- package/bundle/node_modules/undici/lib/web/fetch/index.js +0 -2258
- package/bundle/node_modules/undici/lib/web/fetch/request.js +0 -1099
- package/bundle/node_modules/undici/lib/web/fetch/response.js +0 -636
- package/bundle/node_modules/undici/lib/web/fetch/util.js +0 -1782
- package/bundle/node_modules/undici/lib/web/fetch/webidl.js +0 -740
- package/bundle/node_modules/undici/lib/web/websocket/connection.js +0 -325
- package/bundle/node_modules/undici/lib/web/websocket/constants.js +0 -126
- package/bundle/node_modules/undici/lib/web/websocket/events.js +0 -331
- package/bundle/node_modules/undici/lib/web/websocket/frame.js +0 -138
- package/bundle/node_modules/undici/lib/web/websocket/permessage-deflate.js +0 -70
- package/bundle/node_modules/undici/lib/web/websocket/receiver.js +0 -454
- package/bundle/node_modules/undici/lib/web/websocket/sender.js +0 -109
- package/bundle/node_modules/undici/lib/web/websocket/stream/websocketerror.js +0 -83
- package/bundle/node_modules/undici/lib/web/websocket/stream/websocketstream.js +0 -485
- package/bundle/node_modules/undici/lib/web/websocket/util.js +0 -338
- package/bundle/node_modules/undici/lib/web/websocket/websocket.js +0 -686
- package/bundle/node_modules/undici/package.json +0 -149
- package/bundle/node_modules/undici/scripts/strip-comments.js +0 -10
- package/bundle/node_modules/undici/types/README.md +0 -6
- package/bundle/node_modules/undici/types/agent.d.ts +0 -35
- package/bundle/node_modules/undici/types/api.d.ts +0 -43
- package/bundle/node_modules/undici/types/balanced-pool.d.ts +0 -29
- package/bundle/node_modules/undici/types/cache-interceptor.d.ts +0 -172
- package/bundle/node_modules/undici/types/cache.d.ts +0 -36
- package/bundle/node_modules/undici/types/client-stats.d.ts +0 -15
- package/bundle/node_modules/undici/types/client.d.ts +0 -110
- package/bundle/node_modules/undici/types/connector.d.ts +0 -34
- package/bundle/node_modules/undici/types/content-type.d.ts +0 -21
- package/bundle/node_modules/undici/types/cookies.d.ts +0 -30
- package/bundle/node_modules/undici/types/diagnostics-channel.d.ts +0 -66
- package/bundle/node_modules/undici/types/dispatcher.d.ts +0 -281
- package/bundle/node_modules/undici/types/env-http-proxy-agent.d.ts +0 -21
- package/bundle/node_modules/undici/types/errors.d.ts +0 -171
- package/bundle/node_modules/undici/types/eventsource.d.ts +0 -61
- package/bundle/node_modules/undici/types/fetch.d.ts +0 -210
- package/bundle/node_modules/undici/types/formdata.d.ts +0 -108
- package/bundle/node_modules/undici/types/global-dispatcher.d.ts +0 -9
- package/bundle/node_modules/undici/types/global-origin.d.ts +0 -7
- package/bundle/node_modules/undici/types/h2c-client.d.ts +0 -75
- package/bundle/node_modules/undici/types/handlers.d.ts +0 -15
- package/bundle/node_modules/undici/types/header.d.ts +0 -160
- package/bundle/node_modules/undici/types/index.d.ts +0 -75
- package/bundle/node_modules/undici/types/interceptors.d.ts +0 -34
- package/bundle/node_modules/undici/types/mock-agent.d.ts +0 -68
- package/bundle/node_modules/undici/types/mock-call-history.d.ts +0 -111
- package/bundle/node_modules/undici/types/mock-client.d.ts +0 -25
- package/bundle/node_modules/undici/types/mock-errors.d.ts +0 -12
- package/bundle/node_modules/undici/types/mock-interceptor.d.ts +0 -93
- package/bundle/node_modules/undici/types/mock-pool.d.ts +0 -25
- package/bundle/node_modules/undici/types/patch.d.ts +0 -29
- package/bundle/node_modules/undici/types/pool-stats.d.ts +0 -19
- package/bundle/node_modules/undici/types/pool.d.ts +0 -41
- package/bundle/node_modules/undici/types/proxy-agent.d.ts +0 -29
- package/bundle/node_modules/undici/types/readable.d.ts +0 -68
- package/bundle/node_modules/undici/types/retry-agent.d.ts +0 -8
- package/bundle/node_modules/undici/types/retry-handler.d.ts +0 -116
- package/bundle/node_modules/undici/types/util.d.ts +0 -18
- package/bundle/node_modules/undici/types/utility.d.ts +0 -7
- package/bundle/node_modules/undici/types/webidl.d.ts +0 -266
- package/bundle/node_modules/undici/types/websocket.d.ts +0 -184
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Client Lifecycle
|
|
2
|
-
|
|
3
|
-
An Undici [Client](/docs/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.
|
|
4
|
-
|
|
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
|
-
|
|
7
|
-
## State Transition Overview
|
|
8
|
-
|
|
9
|
-
* A `Client` begins in the **idle** state with no socket connection and no requests in queue.
|
|
10
|
-
* The *connect* event transitions the `Client` to the **pending** state where requests can be queued prior to processing.
|
|
11
|
-
* The *close* and *destroy* events transition the `Client` to the **destroyed** state. Since there are no requests in the queue, the *close* event immediately transitions to the **destroyed** state.
|
|
12
|
-
* The **pending** state indicates the underlying socket connection has been successfully established and requests are queueing.
|
|
13
|
-
* The *process* event transitions the `Client` to the **processing** state where requests are processed.
|
|
14
|
-
* If requests are queued, the *close* event transitions to the **processing** state; otherwise, it transitions to the **destroyed** state.
|
|
15
|
-
* The *destroy* event transitions to the **destroyed** state.
|
|
16
|
-
* The **processing** state initializes to the **processing.running** state.
|
|
17
|
-
* If the current request requires draining, the *needDrain* event transitions the `Client` into the **processing.busy** state which will return to the **processing.running** state with the *drainComplete* event.
|
|
18
|
-
* After all queued requests are completed, the *keepalive* event transitions the `Client` back to the **pending** state. If no requests are queued during the timeout, the **close** event transitions the `Client` to the **destroyed** state.
|
|
19
|
-
* If the *close* event is fired while the `Client` still has queued requests, the `Client` transitions to the **process.closing** state where it will complete all existing requests before firing the *done* event.
|
|
20
|
-
* The *done* event gracefully transitions the `Client` to the **destroyed** state.
|
|
21
|
-
* At any point in time, the *destroy* event will transition the `Client` from the **processing** state to the **destroyed** state, destroying any queued requests.
|
|
22
|
-
* The **destroyed** state is a final state and the `Client` is no longer functional.
|
|
23
|
-
|
|
24
|
-
A state diagram representing an Undici Client instance:
|
|
25
|
-
|
|
26
|
-
```mermaid
|
|
27
|
-
stateDiagram-v2
|
|
28
|
-
[*] --> idle
|
|
29
|
-
idle --> pending : connect
|
|
30
|
-
idle --> destroyed : destroy/close
|
|
31
|
-
|
|
32
|
-
pending --> idle : timeout
|
|
33
|
-
pending --> destroyed : destroy
|
|
34
|
-
|
|
35
|
-
state close_fork <<fork>>
|
|
36
|
-
pending --> close_fork : close
|
|
37
|
-
close_fork --> processing
|
|
38
|
-
close_fork --> destroyed
|
|
39
|
-
|
|
40
|
-
pending --> processing : process
|
|
41
|
-
|
|
42
|
-
processing --> pending : keepalive
|
|
43
|
-
processing --> destroyed : done
|
|
44
|
-
processing --> destroyed : destroy
|
|
45
|
-
|
|
46
|
-
destroyed --> [*]
|
|
47
|
-
|
|
48
|
-
state processing {
|
|
49
|
-
[*] --> running
|
|
50
|
-
running --> closing : close
|
|
51
|
-
running --> busy : needDrain
|
|
52
|
-
busy --> running : drainComplete
|
|
53
|
-
running --> [*] : keepalive
|
|
54
|
-
closing --> [*] : done
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
## State details
|
|
58
|
-
|
|
59
|
-
### idle
|
|
60
|
-
|
|
61
|
-
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/docs/api/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()`](/docs/docs/api/Client.md#clientupgradeoptions-callback)), the `Client` instance will transition from **idle** to [**pending**](/docs/docs/api/Client.md#pending) and then most likely directly to [**processing**](/docs/docs/api/Client.md#processing).
|
|
62
|
-
|
|
63
|
-
Calling [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback) or [`Client.destroy()`](Client.md#clientdestroyerror-callback) transitions directly to the [**destroyed**](/docs/docs/api/Client.md#destroyed) state since the `Client` instance will have no queued requests in this state.
|
|
64
|
-
|
|
65
|
-
### pending
|
|
66
|
-
|
|
67
|
-
The **pending** state signifies a non-processing `Client`. Upon entering this state, the `Client` establishes a socket connection and emits the [`'connect'`](/docs/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.
|
|
68
|
-
|
|
69
|
-
Calling [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback) with queued requests, transitions the `Client` to the [**processing**](/docs/docs/api/Client.md#processing) state. Without queued requests, it transitions to the [**destroyed**](/docs/docs/api/Client.md#destroyed) state.
|
|
70
|
-
|
|
71
|
-
Calling [`Client.destroy()`](/docs/docs/api/Client.md#clientdestroyerror-callback) transitions directly to the [**destroyed**](/docs/docs/api/Client.md#destroyed) state regardless of existing requests.
|
|
72
|
-
|
|
73
|
-
### processing
|
|
74
|
-
|
|
75
|
-
The **processing** state is a state machine within itself. It initializes to the [**processing.running**](/docs/docs/api/Client.md#running) state. The [`Client.dispatch()`](/docs/docs/api/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**](/docs/docs/api/Client.md#closing) state. And `Client.destroy()` will transition to [**destroyed**](/docs/docs/api/Client.md#destroyed).
|
|
76
|
-
|
|
77
|
-
#### running
|
|
78
|
-
|
|
79
|
-
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**](/docs/docs/api/Client.md#busy) sub-state. The *close* event transitions the Client to the [**process.closing**](/docs/docs/api/Client.md#closing) sub-state. If all queued requests are processed and neither [`Client.close()`](/docs/docs/api/Client.md#clientclosecallback) nor [`Client.destroy()`](Client.md#clientdestroyerror-callback) are called, then the [**processing**](/docs/docs/api/Client.md#processing) machine will trigger a *keepalive* event transitioning the `Client` back to the [**pending**](/docs/docs/api/Client.md#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**](/docs/docs/api/Client.md#idle) state.
|
|
80
|
-
|
|
81
|
-
#### busy
|
|
82
|
-
|
|
83
|
-
This sub-state is only entered when a request body is an instance of [Stream](https://nodejs.org/api/stream.html) and requires draining. The `Client` cannot process additional requests while in this state and must wait until the currently processing request body is completely drained before transitioning back to [**processing.running**](/docs/docs/api/Client.md#running).
|
|
84
|
-
|
|
85
|
-
#### closing
|
|
86
|
-
|
|
87
|
-
This sub-state is only entered when a `Client` instance has queued requests and the [`Client.close()`](/docs/docs/api/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**](/docs/docs/api/Client.md#destroyed) state without an error.
|
|
88
|
-
|
|
89
|
-
### destroyed
|
|
90
|
-
|
|
91
|
-
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`.
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Client certificate
|
|
2
|
-
|
|
3
|
-
Client certificate authentication can be configured with the `Client`, the required options are passed along through the `connect` option.
|
|
4
|
-
|
|
5
|
-
The client certificates must be signed by a trusted CA. The Node.js default is to trust the well-known CAs curated by Mozilla.
|
|
6
|
-
|
|
7
|
-
Setting the server option `requestCert: true` tells the server to request the client certificate.
|
|
8
|
-
|
|
9
|
-
The server option `rejectUnauthorized: false` allows us to handle any invalid certificate errors in client code. The `authorized` property on the socket of the incoming request will show if the client certificate was valid. The `authorizationError` property will give the reason if the certificate was not valid.
|
|
10
|
-
|
|
11
|
-
### Client Certificate Authentication
|
|
12
|
-
|
|
13
|
-
```js
|
|
14
|
-
const { readFileSync } = require('node:fs')
|
|
15
|
-
const { join } = require('node:path')
|
|
16
|
-
const { createServer } = require('node:https')
|
|
17
|
-
const { Client } = require('undici')
|
|
18
|
-
|
|
19
|
-
const serverOptions = {
|
|
20
|
-
ca: [
|
|
21
|
-
readFileSync(join(__dirname, 'client-ca-crt.pem'), 'utf8')
|
|
22
|
-
],
|
|
23
|
-
key: readFileSync(join(__dirname, 'server-key.pem'), 'utf8'),
|
|
24
|
-
cert: readFileSync(join(__dirname, 'server-crt.pem'), 'utf8'),
|
|
25
|
-
requestCert: true,
|
|
26
|
-
rejectUnauthorized: false
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const server = createServer(serverOptions, (req, res) => {
|
|
30
|
-
// true if client cert is valid
|
|
31
|
-
if(req.client.authorized === true) {
|
|
32
|
-
console.log('valid')
|
|
33
|
-
} else {
|
|
34
|
-
console.error(req.client.authorizationError)
|
|
35
|
-
}
|
|
36
|
-
res.end()
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
server.listen(0, function () {
|
|
40
|
-
const tls = {
|
|
41
|
-
ca: [
|
|
42
|
-
readFileSync(join(__dirname, 'server-ca-crt.pem'), 'utf8')
|
|
43
|
-
],
|
|
44
|
-
key: readFileSync(join(__dirname, 'client-key.pem'), 'utf8'),
|
|
45
|
-
cert: readFileSync(join(__dirname, 'client-crt.pem'), 'utf8'),
|
|
46
|
-
rejectUnauthorized: false,
|
|
47
|
-
servername: 'agent1'
|
|
48
|
-
}
|
|
49
|
-
const client = new Client(`https://localhost:${server.address().port}`, {
|
|
50
|
-
connect: tls
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
client.request({
|
|
54
|
-
path: '/',
|
|
55
|
-
method: 'GET'
|
|
56
|
-
}, (err, { body }) => {
|
|
57
|
-
body.on('data', (buf) => {})
|
|
58
|
-
body.on('end', () => {
|
|
59
|
-
client.close()
|
|
60
|
-
server.close()
|
|
61
|
-
})
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
```
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
# Mocking Request
|
|
2
|
-
|
|
3
|
-
Undici has its own mocking [utility](/docs/docs/api/MockAgent.md). It allow us to intercept undici HTTP requests and return mocked values instead. It can be useful for testing purposes.
|
|
4
|
-
|
|
5
|
-
Example:
|
|
6
|
-
|
|
7
|
-
```js
|
|
8
|
-
// bank.mjs
|
|
9
|
-
import { request } from 'undici'
|
|
10
|
-
|
|
11
|
-
export async function bankTransfer(recipient, amount) {
|
|
12
|
-
const { body } = await request('http://localhost:3000/bank-transfer',
|
|
13
|
-
{
|
|
14
|
-
method: 'POST',
|
|
15
|
-
headers: {
|
|
16
|
-
'X-TOKEN-SECRET': 'SuperSecretToken',
|
|
17
|
-
},
|
|
18
|
-
body: JSON.stringify({
|
|
19
|
-
recipient,
|
|
20
|
-
amount
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
)
|
|
24
|
-
return await body.json()
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
And this is what the test file looks like:
|
|
29
|
-
|
|
30
|
-
```js
|
|
31
|
-
// index.test.mjs
|
|
32
|
-
import { strict as assert } from 'node:assert'
|
|
33
|
-
import { MockAgent, setGlobalDispatcher, } from 'undici'
|
|
34
|
-
import { bankTransfer } from './bank.mjs'
|
|
35
|
-
|
|
36
|
-
const mockAgent = new MockAgent();
|
|
37
|
-
|
|
38
|
-
setGlobalDispatcher(mockAgent);
|
|
39
|
-
|
|
40
|
-
// Provide the base url to the request
|
|
41
|
-
const mockPool = mockAgent.get('http://localhost:3000');
|
|
42
|
-
|
|
43
|
-
// intercept the request
|
|
44
|
-
mockPool.intercept({
|
|
45
|
-
path: '/bank-transfer',
|
|
46
|
-
method: 'POST',
|
|
47
|
-
headers: {
|
|
48
|
-
'X-TOKEN-SECRET': 'SuperSecretToken',
|
|
49
|
-
},
|
|
50
|
-
body: JSON.stringify({
|
|
51
|
-
recipient: '1234567890',
|
|
52
|
-
amount: '100'
|
|
53
|
-
})
|
|
54
|
-
}).reply(200, {
|
|
55
|
-
message: 'transaction processed'
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
const success = await bankTransfer('1234567890', '100')
|
|
59
|
-
|
|
60
|
-
assert.deepEqual(success, { message: 'transaction processed' })
|
|
61
|
-
|
|
62
|
-
// if you dont want to check whether the body or the headers contain the same value
|
|
63
|
-
// just remove it from interceptor
|
|
64
|
-
mockPool.intercept({
|
|
65
|
-
path: '/bank-transfer',
|
|
66
|
-
method: 'POST',
|
|
67
|
-
}).reply(400, {
|
|
68
|
-
message: 'bank account not found'
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const badRequest = await bankTransfer('1234567890', '100')
|
|
72
|
-
|
|
73
|
-
assert.deepEqual(badRequest, { message: 'bank account not found' })
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Explore other MockAgent functionality [here](/docs/docs/api/MockAgent.md)
|
|
77
|
-
|
|
78
|
-
## Access agent call history
|
|
79
|
-
|
|
80
|
-
Using a MockAgent also allows you to make assertions on the configuration used to make your request in your application.
|
|
81
|
-
|
|
82
|
-
Here is an example :
|
|
83
|
-
|
|
84
|
-
```js
|
|
85
|
-
// index.test.mjs
|
|
86
|
-
import { strict as assert } from 'node:assert'
|
|
87
|
-
import { MockAgent, setGlobalDispatcher, fetch } from 'undici'
|
|
88
|
-
import { app } from './app.mjs'
|
|
89
|
-
|
|
90
|
-
// given an application server running on http://localhost:3000
|
|
91
|
-
await app.start()
|
|
92
|
-
|
|
93
|
-
// enable call history at instantiation
|
|
94
|
-
const mockAgent = new MockAgent({ enableCallHistory: true })
|
|
95
|
-
// or after instantiation
|
|
96
|
-
mockAgent.enableCallHistory()
|
|
97
|
-
|
|
98
|
-
setGlobalDispatcher(mockAgent)
|
|
99
|
-
|
|
100
|
-
// this call is made (not intercepted)
|
|
101
|
-
await fetch(`http://localhost:3000/endpoint?query='hello'`, {
|
|
102
|
-
method: 'POST',
|
|
103
|
-
headers: { 'content-type': 'application/json' }
|
|
104
|
-
body: JSON.stringify({ data: '' })
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
// access to the call history of the MockAgent (which register every call made intercepted or not)
|
|
108
|
-
assert.ok(mockAgent.getCallHistory()?.calls().length === 1)
|
|
109
|
-
assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.fullUrl, `http://localhost:3000/endpoint?query='hello'`)
|
|
110
|
-
assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.body, JSON.stringify({ data: '' }))
|
|
111
|
-
assert.deepStrictEqual(mockAgent.getCallHistory()?.firstCall()?.searchParams, { query: 'hello' })
|
|
112
|
-
assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.port, '3000')
|
|
113
|
-
assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.host, 'localhost:3000')
|
|
114
|
-
assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.method, 'POST')
|
|
115
|
-
assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.path, '/endpoint')
|
|
116
|
-
assert.deepStrictEqual(mockAgent.getCallHistory()?.firstCall()?.headers, { 'content-type': 'application/json' })
|
|
117
|
-
|
|
118
|
-
// clear all call history logs
|
|
119
|
-
mockAgent.clearCallHistory()
|
|
120
|
-
|
|
121
|
-
assert.ok(mockAgent.getCallHistory()?.calls().length === 0)
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Calling `mockAgent.close()` will automatically clear and delete every call history for you.
|
|
125
|
-
|
|
126
|
-
Explore other MockAgent functionality [here](/docs/docs/api/MockAgent.md)
|
|
127
|
-
|
|
128
|
-
Explore other MockCallHistory functionality [here](/docs/docs/api/MockCallHistory.md)
|
|
129
|
-
|
|
130
|
-
Explore other MockCallHistoryLog functionality [here](/docs/docs/api/MockCallHistoryLog.md)
|
|
131
|
-
|
|
132
|
-
## Debug Mock Value
|
|
133
|
-
|
|
134
|
-
When the interceptor and the request options are not the same, undici will automatically make a real HTTP request. To prevent real requests from being made, use `mockAgent.disableNetConnect()`:
|
|
135
|
-
|
|
136
|
-
```js
|
|
137
|
-
const mockAgent = new MockAgent();
|
|
138
|
-
|
|
139
|
-
setGlobalDispatcher(mockAgent);
|
|
140
|
-
mockAgent.disableNetConnect()
|
|
141
|
-
|
|
142
|
-
// Provide the base url to the request
|
|
143
|
-
const mockPool = mockAgent.get('http://localhost:3000');
|
|
144
|
-
|
|
145
|
-
mockPool.intercept({
|
|
146
|
-
path: '/bank-transfer',
|
|
147
|
-
method: 'POST',
|
|
148
|
-
}).reply(200, {
|
|
149
|
-
message: 'transaction processed'
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
const badRequest = await bankTransfer('1234567890', '100')
|
|
153
|
-
// Will throw an error
|
|
154
|
-
// MockNotMatchedError: Mock dispatch not matched for path '/bank-transfer':
|
|
155
|
-
// subsequent request to origin http://localhost:3000 was not allowed (net.connect disabled)
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## Reply with data based on request
|
|
159
|
-
|
|
160
|
-
If the mocked response needs to be dynamically derived from the request parameters, you can provide a function instead of an object to `reply`:
|
|
161
|
-
|
|
162
|
-
```js
|
|
163
|
-
mockPool.intercept({
|
|
164
|
-
path: '/bank-transfer',
|
|
165
|
-
method: 'POST',
|
|
166
|
-
headers: {
|
|
167
|
-
'X-TOKEN-SECRET': 'SuperSecretToken',
|
|
168
|
-
},
|
|
169
|
-
body: JSON.stringify({
|
|
170
|
-
recipient: '1234567890',
|
|
171
|
-
amount: '100'
|
|
172
|
-
})
|
|
173
|
-
}).reply(200, (opts) => {
|
|
174
|
-
// do something with opts
|
|
175
|
-
|
|
176
|
-
return { message: 'transaction processed' }
|
|
177
|
-
})
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
in this case opts will be
|
|
181
|
-
|
|
182
|
-
```
|
|
183
|
-
{
|
|
184
|
-
method: 'POST',
|
|
185
|
-
headers: { 'X-TOKEN-SECRET': 'SuperSecretToken' },
|
|
186
|
-
body: '{"recipient":"1234567890","amount":"100"}',
|
|
187
|
-
origin: 'http://localhost:3000',
|
|
188
|
-
path: '/bank-transfer'
|
|
189
|
-
}
|
|
190
|
-
```
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# Connecting through a proxy
|
|
2
|
-
|
|
3
|
-
Connecting through a proxy is possible by:
|
|
4
|
-
|
|
5
|
-
- Using [ProxyAgent](/docs/docs/api/ProxyAgent.md).
|
|
6
|
-
- Configuring `Client` or `Pool` constructor.
|
|
7
|
-
|
|
8
|
-
The proxy url should be passed to the `Client` or `Pool` constructor, while the upstream server url
|
|
9
|
-
should be added to every request call in the `path`.
|
|
10
|
-
For instance, if you need to send a request to the `/hello` route of your upstream server,
|
|
11
|
-
the `path` should be `path: 'http://upstream.server:port/hello?foo=bar'`.
|
|
12
|
-
|
|
13
|
-
If you proxy requires basic authentication, you can send it via the `proxy-authorization` header.
|
|
14
|
-
|
|
15
|
-
### Connect without authentication
|
|
16
|
-
|
|
17
|
-
```js
|
|
18
|
-
import { Client } from 'undici'
|
|
19
|
-
import { createServer } from 'http'
|
|
20
|
-
import { createProxy } from 'proxy'
|
|
21
|
-
|
|
22
|
-
const server = await buildServer()
|
|
23
|
-
const proxyServer = await buildProxy()
|
|
24
|
-
|
|
25
|
-
const serverUrl = `http://localhost:${server.address().port}`
|
|
26
|
-
const proxyUrl = `http://localhost:${proxyServer.address().port}`
|
|
27
|
-
|
|
28
|
-
server.on('request', (req, res) => {
|
|
29
|
-
console.log(req.url) // '/hello?foo=bar'
|
|
30
|
-
res.setHeader('content-type', 'application/json')
|
|
31
|
-
res.end(JSON.stringify({ hello: 'world' }))
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
const client = new Client(proxyUrl)
|
|
35
|
-
|
|
36
|
-
const response = await client.request({
|
|
37
|
-
method: 'GET',
|
|
38
|
-
path: serverUrl + '/hello?foo=bar'
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
response.body.setEncoding('utf8')
|
|
42
|
-
let data = ''
|
|
43
|
-
for await (const chunk of response.body) {
|
|
44
|
-
data += chunk
|
|
45
|
-
}
|
|
46
|
-
console.log(response.statusCode) // 200
|
|
47
|
-
console.log(JSON.parse(data)) // { hello: 'world' }
|
|
48
|
-
|
|
49
|
-
server.close()
|
|
50
|
-
proxyServer.close()
|
|
51
|
-
client.close()
|
|
52
|
-
|
|
53
|
-
function buildServer () {
|
|
54
|
-
return new Promise((resolve, reject) => {
|
|
55
|
-
const server = createServer()
|
|
56
|
-
server.listen(0, () => resolve(server))
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function buildProxy () {
|
|
61
|
-
return new Promise((resolve, reject) => {
|
|
62
|
-
const server = createProxy(createServer())
|
|
63
|
-
server.listen(0, () => resolve(server))
|
|
64
|
-
})
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Connect with authentication
|
|
69
|
-
|
|
70
|
-
```js
|
|
71
|
-
import { Client } from 'undici'
|
|
72
|
-
import { createServer } from 'http'
|
|
73
|
-
import { createProxy } from 'proxy'
|
|
74
|
-
|
|
75
|
-
const server = await buildServer()
|
|
76
|
-
const proxyServer = await buildProxy()
|
|
77
|
-
|
|
78
|
-
const serverUrl = `http://localhost:${server.address().port}`
|
|
79
|
-
const proxyUrl = `http://localhost:${proxyServer.address().port}`
|
|
80
|
-
|
|
81
|
-
proxyServer.authenticate = function (req) {
|
|
82
|
-
return req.headers['proxy-authorization'] === `Basic ${Buffer.from('user:pass').toString('base64')}`
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
server.on('request', (req, res) => {
|
|
86
|
-
console.log(req.url) // '/hello?foo=bar'
|
|
87
|
-
res.setHeader('content-type', 'application/json')
|
|
88
|
-
res.end(JSON.stringify({ hello: 'world' }))
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
const client = new Client(proxyUrl)
|
|
92
|
-
|
|
93
|
-
const response = await client.request({
|
|
94
|
-
method: 'GET',
|
|
95
|
-
path: serverUrl + '/hello?foo=bar',
|
|
96
|
-
headers: {
|
|
97
|
-
'proxy-authorization': `Basic ${Buffer.from('user:pass').toString('base64')}`
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
response.body.setEncoding('utf8')
|
|
102
|
-
let data = ''
|
|
103
|
-
for await (const chunk of response.body) {
|
|
104
|
-
data += chunk
|
|
105
|
-
}
|
|
106
|
-
console.log(response.statusCode) // 200
|
|
107
|
-
console.log(JSON.parse(data)) // { hello: 'world' }
|
|
108
|
-
|
|
109
|
-
server.close()
|
|
110
|
-
proxyServer.close()
|
|
111
|
-
client.close()
|
|
112
|
-
|
|
113
|
-
function buildServer () {
|
|
114
|
-
return new Promise((resolve, reject) => {
|
|
115
|
-
const server = createServer()
|
|
116
|
-
server.listen(0, () => resolve(server))
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function buildProxy () {
|
|
121
|
-
return new Promise((resolve, reject) => {
|
|
122
|
-
const server = createProxy(createServer())
|
|
123
|
-
server.listen(0, () => resolve(server))
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# Writing tests
|
|
2
|
-
|
|
3
|
-
Undici is tuned for a production use case and its default will keep
|
|
4
|
-
a socket open for a few seconds after an HTTP request is completed to
|
|
5
|
-
remove the overhead of opening up a new socket. These settings that makes
|
|
6
|
-
Undici shine in production are not a good fit for using Undici in automated
|
|
7
|
-
tests, as it will result in longer execution times.
|
|
8
|
-
|
|
9
|
-
The following are good defaults that will keep the socket open for only 10ms:
|
|
10
|
-
|
|
11
|
-
```js
|
|
12
|
-
import { request, setGlobalDispatcher, Agent } from 'undici'
|
|
13
|
-
|
|
14
|
-
const agent = new Agent({
|
|
15
|
-
keepAliveTimeout: 10, // milliseconds
|
|
16
|
-
keepAliveMaxTimeout: 10 // milliseconds
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
setGlobalDispatcher(agent)
|
|
20
|
-
```
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global')
|
|
4
|
-
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
|
|
5
|
-
const fetchImpl = require('./lib/web/fetch').fetch
|
|
6
|
-
|
|
7
|
-
module.exports.fetch = function fetch (resource, init = undefined) {
|
|
8
|
-
return fetchImpl(resource, init).catch((err) => {
|
|
9
|
-
if (err && typeof err === 'object') {
|
|
10
|
-
Error.captureStackTrace(err)
|
|
11
|
-
}
|
|
12
|
-
throw err
|
|
13
|
-
})
|
|
14
|
-
}
|
|
15
|
-
module.exports.FormData = require('./lib/web/fetch/formdata').FormData
|
|
16
|
-
module.exports.Headers = require('./lib/web/fetch/headers').Headers
|
|
17
|
-
module.exports.Response = require('./lib/web/fetch/response').Response
|
|
18
|
-
module.exports.Request = require('./lib/web/fetch/request').Request
|
|
19
|
-
|
|
20
|
-
const { CloseEvent, ErrorEvent, MessageEvent, createFastMessageEvent } = require('./lib/web/websocket/events')
|
|
21
|
-
module.exports.WebSocket = require('./lib/web/websocket/websocket').WebSocket
|
|
22
|
-
module.exports.CloseEvent = CloseEvent
|
|
23
|
-
module.exports.ErrorEvent = ErrorEvent
|
|
24
|
-
module.exports.MessageEvent = MessageEvent
|
|
25
|
-
module.exports.createFastMessageEvent = createFastMessageEvent
|
|
26
|
-
|
|
27
|
-
module.exports.EventSource = require('./lib/web/eventsource/eventsource').EventSource
|
|
28
|
-
|
|
29
|
-
const api = require('./lib/api')
|
|
30
|
-
const Dispatcher = require('./lib/dispatcher/dispatcher')
|
|
31
|
-
Object.assign(Dispatcher.prototype, api)
|
|
32
|
-
// Expose the fetch implementation to be enabled in Node.js core via a flag
|
|
33
|
-
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
|
|
34
|
-
module.exports.getGlobalDispatcher = getGlobalDispatcher
|
|
35
|
-
module.exports.setGlobalDispatcher = setGlobalDispatcher
|