undici
Version:
An HTTP/1.1 client, written from scratch for Node.js
219 lines (143 loc) • 8.79 kB
Markdown
# undici
[](https://github.com/nodejs/undici/actions/workflows/nodejs.yml) [](http://standardjs.com/) [](https://badge.fury.io/js/undici) [](https://codecov.io/gh/nodejs/undici)
A HTTP/1.1 client, written from scratch for Node.js.
> Undici means eleven in Italian. 1.1 -> 11 -> Eleven -> Undici.
It is also a Stranger Things reference.
Have a question about using Undici? Open a [Q&A Discussion](https://github.com/nodejs/undici/discussions/new) or join our official OpenJS [Slack](https://openjs-foundation.slack.com/archives/C01QF9Q31QD) channel.
## Install
```
npm i undici
```
## Benchmarks
The benchmark is a simple `hello world` [example](benchmarks/benchmark.js) using a
number of unix sockets (connections) with a pipelining depth of 10 running on Node 16.
The benchmarks below have the [simd](https://github.com/WebAssembly/simd) feature enabled.
### Connections 1
| Tests | Samples | Result | Tolerance | Difference with slowest |
|---------------------|---------|---------------|-----------|-------------------------|
| http - no keepalive | 15 | 4.63 req/sec | ± 2.77 % | - |
| http - keepalive | 10 | 4.81 req/sec | ± 2.16 % | + 3.94 % |
| undici - stream | 25 | 62.22 req/sec | ± 2.67 % | + 1244.58 % |
| undici - dispatch | 15 | 64.33 req/sec | ± 2.47 % | + 1290.24 % |
| undici - request | 15 | 66.08 req/sec | ± 2.48 % | + 1327.88 % |
| undici - pipeline | 10 | 66.13 req/sec | ± 1.39 % | + 1329.08 % |
### Connections 50
| Tests | Samples | Result | Tolerance | Difference with slowest |
|---------------------|---------|------------------|-----------|-------------------------|
| http - no keepalive | 50 | 3546.49 req/sec | ± 2.90 % | - |
| http - keepalive | 15 | 5692.67 req/sec | ± 2.48 % | + 60.52 % |
| undici - pipeline | 25 | 8478.71 req/sec | ± 2.62 % | + 139.07 % |
| undici - request | 20 | 9766.66 req/sec | ± 2.79 % | + 175.39 % |
| undici - stream | 15 | 10109.74 req/sec | ± 2.94 % | + 185.06 % |
| undici - dispatch | 25 | 10949.73 req/sec | ± 2.54 % | + 208.75 % |
## Quick Start
```js
import { request } from 'undici'
const {
statusCode,
headers,
trailers,
body
} = await request('http://localhost:3000/foo')
console.log('response received', statusCode)
console.log('headers', headers)
for await (const data of body) {
console.log('data', data)
}
console.log('trailers', trailers)
```
## Common API Methods
This section documents our most commonly used API methods. Additional APIs are documented in their own files within the [docs](./docs/) folder and are accessible via the navigation list on the left side of the docs site.
### `undici.request([url, options]): Promise`
Arguments:
* **url** `string | URL | object`
* **options** [`RequestOptions`](./docs/api/Dispatcher.md#parameter-requestoptions)
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
* **maxRedirections** `Integer` - Default: `0`
Returns a promise with the result of the `Dispatcher.request` method.
Calls `options.dispatcher.request(options)`.
See [Dispatcher.request](./docs/api/Dispatcher.md#dispatcherrequestoptions-callback) for more details.
### `undici.stream([url, options, ]factory): Promise`
Arguments:
* **url** `string | URL | object`
* **options** [`StreamOptions`](./docs/api/Dispatcher.md#parameter-streamoptions)
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
* **maxRedirections** `Integer` - Default: `0`
* **factory** `Dispatcher.stream.factory`
Returns a promise with the result of the `Dispatcher.stream` method.
Calls `options.dispatcher.stream(options, factory)`.
See [Dispatcher.stream](docs/api/Dispatcher.md#dispatcherstream) for more details.
### `undici.pipeline([url, options, ]handler): Duplex`
Arguments:
* **url** `string | URL | object`
* **options** [`PipelineOptions`](docs/api/Dispatcher.md#parameter-pipelineoptions)
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
* **maxRedirections** `Integer` - Default: `0`
* **handler** `Dispatcher.pipeline.handler`
Returns: `stream.Duplex`
Calls `options.dispatch.pipeline(options, handler)`.
See [Dispatcher.pipeline](docs/api/Dispatcher.md#dispatcherpipeline) for more details.
### `undici.connect([url, options]): Promise`
Starts two-way communications with the requested resource using [HTTP CONNECT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT).
Arguments:
* **url** `string | URL | object`
* **options** [`ConnectOptions`](docs/api/Dispatcher.md#parameter-connectoptions)
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
* **maxRedirections** `Integer` - Default: `0`
* **callback** `(err: Error | null, data: ConnectData | null) => void` (optional)
Returns a promise with the result of the `Dispatcher.connect` method.
Calls `options.dispatch.connect(options)`.
See [Dispatcher.connect](docs/api/Dispatcher.md#dispatcherconnect) for more details.
### `undici.upgrade([url, options]): Promise`
Upgrade to a different protocol. See [MDN - HTTP - Protocol upgrade mechanism](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) for more details.
Arguments:
* **url** `string | URL | object`
* **options** [`UpgradeOptions`](docs/api/Dispatcher.md#parameter-upgradeoptions)
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
* **maxRedirections** `Integer` - Default: `0`
* **callback** `(error: Error | null, data: UpgradeData) => void` (optional)
Returns a promise with the result of the `Dispatcher.upgrade` method.
Calls `options.dispatcher.upgrade(options)`.
See [Dispatcher.upgrade](docs/api/Dispatcher.md#dispatcherupgradeoptions-callback) for more details.
### `undici.setGlobalDispatcher(dispatcher)`
* dispatcher `Dispatcher`
Sets the global dispatcher used by Common API Methods.
### `undici.getGlobalDispatcher()`
Gets the global dispatcher used by Common API Methods.
Returns: `Dispatcher`
## Specification Compliance
This section documents parts of the HTTP/1.1 specification which Undici does
not support or does not fully implement.
### Expect
Undici does not support the `Expect` request header field. The request
body is always immediately sent and the `100 Continue` response will be
ignored.
Refs: https://tools.ietf.org/html/rfc7231#section-5.1.1
### Pipelining
Undici will only use pipelining if configured with a `pipelining` factor
greater than `1`.
Undici always assumes that connections are persistent and will immediately
pipeline requests, without checking whether the connection is persistent.
Hence, automatic fallback to HTTP/1.0 or HTTP/1.1 without pipelining is
not supported.
Undici will immediately pipeline when retrying requests afters a failed
connection. However, Undici will not retry the first remaining requests in
the prior pipeline and instead error the corresponding callback/promise/stream.
Undici will abort all running requests in the pipeline when any of them are
aborted.
* Refs: https://tools.ietf.org/html/rfc2616#section-8.1.2.2
* Refs: https://tools.ietf.org/html/rfc7230#section-6.3.2
## Collaborators
* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood>
* [__Daniele Belardi__](https://github.com/dnlup), <https://www.npmjs.com/~dnlup>
* [__Tomas Della Vedova__](https://github.com/delvedor), <https://www.npmjs.com/~delvedor>
* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
### Releasers
* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
## License
MIT