• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Class: Client
2
3Extends: `undici.Dispatcher`
4
5A basic HTTP/1.1 client, mapped on top a single TCP/TLS connection. Pipelining is disabled by default.
6
7Requests are not guaranteed to be dispatched in order of invocation.
8
9## `new Client(url[, options])`
10
11Arguments:
12
13* **url** `URL | string` - Should only include the **protocol, hostname, and port**.
14* **options** `ClientOptions` (optional)
15
16Returns: `Client`
17
18### Parameter: `ClientOptions`
19
20> ⚠️ Warning: The `H2` support is experimental.
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.
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* **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* **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.
26* **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `1e3` - A number of milliseconds subtracted from server *keep-alive* hints when overriding `keepAliveTimeout` to account for timing inaccuracies caused by e.g. transport latency. Defaults to 1 second.
27* **maxHeaderSize** `number | null` (optional) - Default: `--max-http-header-size` or `16384` - The maximum length of request headers in bytes. Defaults to Node.js' --max-http-header-size or 16KiB.
28* **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable.
29* **pipelining** `number | null` (optional) - Default: `1` - The amount of concurrent requests to be sent over the single TCP/TLS connection according to [RFC7230](https://tools.ietf.org/html/rfc7230#section-6.3.2). Carefully consider your workload and environment before enabling concurrent requests as pipelining may reduce performance if used incorrectly. Pipelining is sensitive to network stack settings as well as head of line blocking caused by e.g. long running requests. Set to `0` to disable keep-alive connections.
30* **connect** `ConnectOptions | Function | null` (optional) - Default: `null`.
31* **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body.
32* **interceptors** `{ Client: DispatchInterceptor[] }` - Default: `[RedirectInterceptor]` - A list of interceptors that are applied to the dispatch method. Additional logic can be applied (such as, but not limited to: 302 status code handling, authentication, cookies, compression and caching). Note that the behavior of interceptors is Experimental and might change at any given time.
33* **autoSelectFamily**: `boolean` (optional) - Default: depends on local Node version, on Node 18.13.0 and above is `false`. Enables a family autodetection algorithm that loosely implements section 5 of [RFC 8305](https://tools.ietf.org/html/rfc8305#section-5). See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details. This option is ignored if not supported by the current Node version.
34* **autoSelectFamilyAttemptTimeout**: `number` - Default: depends on local Node version, on Node 18.13.0 and above is `250`. The amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details.
35* **allowH2**: `boolean` - Default: `false`. Enables support for H2 if the server has assigned bigger priority to it through ALPN negotiation.
36* **maxConcurrentStreams**: `number` - Default: `100`. Dictates the maximum number of concurrent streams for a single H2 session. It can be overriden by a SETTINGS remote frame.
37
38#### Parameter: `ConnectOptions`
39
40Every Tls option, see [here](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
41Furthermore, the following options can be passed:
42
43* **socketPath** `string | null` (optional) - Default: `null` - An IPC endpoint, either Unix domain socket or Windows named pipe.
44* **maxCachedSessions** `number | null` (optional) - Default: `100` - Maximum number of TLS cached sessions. Use 0 to disable TLS session caching. Default: 100.
45* **timeout** `number | null` (optional) -  In milliseconds, Default `10e3`.
46* **servername** `string | null` (optional)
47* **keepAlive** `boolean | null` (optional) - Default: `true` - TCP keep-alive enabled
48* **keepAliveInitialDelay** `number | null` (optional) - Default: `60000` - TCP keep-alive interval for the socket in milliseconds
49
50### Example - Basic Client instantiation
51
52This will instantiate the undici Client, but it will not connect to the origin until something is queued. Consider using `client.connect` to prematurely connect to the origin, or just call `client.request`.
53
54```js
55'use strict'
56import { Client } from 'undici'
57
58const client = new Client('http://localhost:3000')
59```
60
61### Example - Custom connector
62
63This will allow you to perform some additional check on the socket that will be used for the next request.
64
65```js
66'use strict'
67import { Client, buildConnector } from 'undici'
68
69const connector = buildConnector({ rejectUnauthorized: false })
70const client = new Client('https://localhost:3000', {
71  connect (opts, cb) {
72    connector(opts, (err, socket) => {
73      if (err) {
74        cb(err)
75      } else if (/* assertion */) {
76        socket.destroy()
77        cb(new Error('kaboom'))
78      } else {
79        cb(null, socket)
80      }
81    })
82  }
83})
84```
85
86## Instance Methods
87
88### `Client.close([callback])`
89
90Implements [`Dispatcher.close([callback])`](Dispatcher.md#dispatcherclosecallback-promise).
91
92### `Client.destroy([error, callback])`
93
94Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
95
96Waits until socket is closed before invoking the callback (or returning a promise if no callback is provided).
97
98### `Client.connect(options[, callback])`
99
100See [`Dispatcher.connect(options[, callback])`](Dispatcher.md#dispatcherconnectoptions-callback).
101
102### `Client.dispatch(options, handlers)`
103
104Implements [`Dispatcher.dispatch(options, handlers)`](Dispatcher.md#dispatcherdispatchoptions-handler).
105
106### `Client.pipeline(options, handler)`
107
108See [`Dispatcher.pipeline(options, handler)`](Dispatcher.md#dispatcherpipelineoptions-handler).
109
110### `Client.request(options[, callback])`
111
112See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
113
114### `Client.stream(options, factory[, callback])`
115
116See [`Dispatcher.stream(options, factory[, callback])`](Dispatcher.md#dispatcherstreamoptions-factory-callback).
117
118### `Client.upgrade(options[, callback])`
119
120See [`Dispatcher.upgrade(options[, callback])`](Dispatcher.md#dispatcherupgradeoptions-callback).
121
122## Instance Properties
123
124### `Client.closed`
125
126* `boolean`
127
128`true` after `client.close()` has been called.
129
130### `Client.destroyed`
131
132* `boolean`
133
134`true` after `client.destroyed()` has been called or `client.close()` has been called and the client shutdown has completed.
135
136### `Client.pipelining`
137
138* `number`
139
140Property to get and set the pipelining factor.
141
142## Instance Events
143
144### Event: `'connect'`
145
146See [Dispatcher Event: `'connect'`](Dispatcher.md#event-connect).
147
148Parameters:
149
150* **origin** `URL`
151* **targets** `Array<Dispatcher>`
152
153Emitted when a socket has been created and connected. The client will connect once `client.size > 0`.
154
155#### Example - Client connect event
156
157```js
158import { createServer } from 'http'
159import { Client } from 'undici'
160import { once } from 'events'
161
162const server = createServer((request, response) => {
163  response.end('Hello, World!')
164}).listen()
165
166await once(server, 'listening')
167
168const client = new Client(`http://localhost:${server.address().port}`)
169
170client.on('connect', (origin) => {
171  console.log(`Connected to ${origin}`) // should print before the request body statement
172})
173
174try {
175  const { body } = await client.request({
176    path: '/',
177    method: 'GET'
178  })
179  body.setEncoding('utf-8')
180  body.on('data', console.log)
181  client.close()
182  server.close()
183} catch (error) {
184  console.error(error)
185  client.close()
186  server.close()
187}
188```
189
190### Event: `'disconnect'`
191
192See [Dispatcher Event: `'disconnect'`](Dispatcher.md#event-disconnect).
193
194Parameters:
195
196* **origin** `URL`
197* **targets** `Array<Dispatcher>`
198* **error** `Error`
199
200Emitted when socket has disconnected. The error argument of the event is the error which caused the socket to disconnect. The client will reconnect if or once `client.size > 0`.
201
202#### Example - Client disconnect event
203
204```js
205import { createServer } from 'http'
206import { Client } from 'undici'
207import { once } from 'events'
208
209const server = createServer((request, response) => {
210  response.destroy()
211}).listen()
212
213await once(server, 'listening')
214
215const client = new Client(`http://localhost:${server.address().port}`)
216
217client.on('disconnect', (origin) => {
218  console.log(`Disconnected from ${origin}`)
219})
220
221try {
222  await client.request({
223    path: '/',
224    method: 'GET'
225  })
226} catch (error) {
227  console.error(error.message)
228  client.close()
229  server.close()
230}
231```
232
233### Event: `'drain'`
234
235Emitted when pipeline is no longer busy.
236
237See [Dispatcher Event: `'drain'`](Dispatcher.md#event-drain).
238
239#### Example - Client drain event
240
241```js
242import { createServer } from 'http'
243import { Client } from 'undici'
244import { once } from 'events'
245
246const server = createServer((request, response) => {
247  response.end('Hello, World!')
248}).listen()
249
250await once(server, 'listening')
251
252const client = new Client(`http://localhost:${server.address().port}`)
253
254client.on('drain', () => {
255  console.log('drain event')
256  client.close()
257  server.close()
258})
259
260const requests = [
261  client.request({ path: '/', method: 'GET' }),
262  client.request({ path: '/', method: 'GET' }),
263  client.request({ path: '/', method: 'GET' })
264]
265
266await Promise.all(requests)
267
268console.log('requests completed')
269```
270
271### Event: `'error'`
272
273Invoked for users errors such as throwing in the `onError` handler.
274