Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 278 additions & 0 deletions deps/undici/src/docs/docs/GettingStarted.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
# Getting Started

## Installation

```bash
npm install undici
```

## Fetch

The quickest way to get started is with `fetch`, which follows the
[Fetch Standard](https://fetch.spec.whatwg.org/) and works the same way as
the browser API:

```js
import { fetch } from 'undici'

const res = await fetch('https://example.com')
const data = await res.json()
console.log(data)
```

### Using the Request object

undici also exports a `Request` class that follows the Fetch Standard:

```js
import { fetch, Request } from 'undici'

const req = new Request('https://example.com', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ hello: 'world' })
})
const res = await fetch(req)
console.log(res.status)
```

### Streaming the response

`res.body` is a web `ReadableStream`. Use `pipeline` from
`node:stream/promises` to stream it to a file:

```js
import { fetch } from 'undici'
import { pipeline } from 'node:stream/promises'
import { createWriteStream } from 'node:fs'

const res = await fetch('https://example.com/large-file.zip')
await pipeline(res.body, createWriteStream('./file.zip'))
```

> Always consume or cancel the response body. In Node.js, garbage collection
> is not aggressive enough to release connections promptly, so leaving a body
> unread can cause connection leaks and stalled requests. See
> [Specification Compliance - Garbage Collection](/docs/#garbage-collection)
> for details.

For more on `fetch`, see [API Reference: Fetch](/docs/docs/api/Fetch.md).

## Dispatchers: Connection reuse and pooling

By default, `fetch`, `request`, `stream`, and `pipeline` create a new connection
for each call. For applications that make many requests to the same origin,
this is wasteful. undici provides **dispatchers** that manage connections
internally.

### `Agent` — for requests to multiple origins

`Agent` is the most general-purpose dispatcher. It pools connections per-origin
and is the recommended default for most applications. Use it with
`setGlobalDispatcher` to affect all undici calls globally:

```js
import { Agent, setGlobalDispatcher, fetch } from 'undici'

const agent = new Agent({
keepAliveTimeout: 30_000,
keepAliveMaxTimeout: 600_000
})
setGlobalDispatcher(agent)

// All subsequent fetch/request/stream/pipeline calls reuse connections
const res = await fetch('https://api.example.com/data')
```

You can also pass a dispatcher per-request:

```js
await fetch('https://api.example.com/data', { dispatcher: agent })
```

### `Pool` — for requests to a single origin

`Pool` manages a fixed set of connections to one origin. It gives you explicit
control over concurrency:

```js
import { Pool, request } from 'undici'

const pool = new Pool('https://api.example.com', { connections: 10 })

const { body } = await request('https://api.example.com/data', {
dispatcher: pool
})
const data = await body.json()

pool.close()
```

### `Client` — for a single connection

`Client` maps to a single TCP connection. It supports pipelining (sending
multiple requests before responses arrive):

```js
import { Client } from 'undici'

const client = new Client('https://api.example.com', {
pipelining: 5
})

const { body } = await client.request({ path: '/', method: 'GET' })
await body.dump()

client.close()
```

For more on dispatcher options and lifecycle, see:
- [API Reference: Agent](/docs/docs/api/Agent.md)
- [API Reference: Pool](/docs/docs/api/Pool.md)
- [API Reference: Client](/docs/docs/api/Client.md)

## Timeouts

undici applies timeouts at two levels:

- **`headersTimeout`** — time to wait for response headers (default: 300s).
- **`bodyTimeout`** — time between consecutive body chunks (default: 300s).

Set these on the dispatcher or per-request:

```js
import { Agent, setGlobalDispatcher } from 'undici'

const agent = new Agent({
headersTimeout: 5_000,
bodyTimeout: 30_000
})

setGlobalDispatcher(agent)
```

Timeout errors are thrown as `HeadersTimeoutError` and `BodyTimeoutError`.
See [API Reference: Errors](/docs/docs/api/Errors.md) for the full list.

## Error handling

undici exposes structured errors via `error.code`:

```js
import { request, errors } from 'undici'

try {
const { body } = await request('https://example.com')
await body.json()
} catch (err) {
switch (err.code) {
case 'UND_ERR_CONNECT_TIMEOUT':
console.error('Connection timed out')
break
case 'UND_ERR_HEADERS_TIMEOUT':
console.error('Headers timed out')
break
case 'UND_ERR_BODY_TIMEOUT':
console.error('Body timed out')
break
case 'UND_ERR_ABORTED':
console.error('Request was aborted')
break
default:
console.error(err)
}
}
```

### Aborting requests

```js
import { request } from 'undici'

const ac = new AbortController()

setTimeout(() => ac.abort(), 1000)

try {
const { body } = await request('https://example.com', {
signal: ac.signal
})
await body.dump()
} catch (err) {
console.error(err.code) // UND_ERR_ABORTED
}
```

## Common patterns

### Proxies

Use `ProxyAgent` for HTTP(S) proxies, or `EnvHttpProxyAgent` to pick up
proxy settings from environment variables:

```js
import { ProxyAgent, setGlobalDispatcher } from 'undici'

const proxy = new ProxyAgent('http://proxy.internal:8080')
setGlobalDispatcher(proxy)
```

See [Best Practices: Proxy](/docs/docs/best-practices/proxy.md) and
[API Reference: ProxyAgent](/docs/docs/api/ProxyAgent.md).

### Mocking in tests

```js
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('https://api.example.com')
mockPool.intercept({ path: '/users' }).reply(200, [{ id: 1 }])

const { body } = await request('https://api.example.com/users')
console.log(await body.json())
```

See [Best Practices: Mocking Request](/docs/docs/best-practices/mocking-request.md)
and [API Reference: MockAgent](/docs/docs/api/MockAgent.md).

### Testing with undici

For test suites, set short keep-alive timeouts to avoid slow teardowns:

```js
import { Agent, setGlobalDispatcher } from 'undici'

const agent = new Agent({
keepAliveTimeout: 10,
keepAliveMaxTimeout: 10
})
setGlobalDispatcher(agent)
```

See [Best Practices: Writing Tests](/docs/docs/best-practices/writing-tests.md).

### Customizing the global fetch

You can override Node.js's built-in globals with `install()`:

```js
import { install } from 'undici'

install()

// Global fetch, Headers, Response, Request, and FormData
// now come from undici, not the Node.js bundle
const res = await fetch('https://example.com')
```

See [API Reference: Global Installation](/docs/docs/api/GlobalInstallation.md).

## Further reading

- [Undici vs. Built-in Fetch](/docs/docs/best-practices/undici-vs-builtin-fetch.md) —
when to install undici vs using Node.js built-in fetch
- [API Reference](/docs/docs/api/Dispatcher.md) — full dispatcher API documentation
- [Examples](/docs/examples/) — runnable code examples
2 changes: 1 addition & 1 deletion deps/undici/src/docs/docs/api/BalancedPool.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Implements [Client.closed](/docs/docs/api/Client.md#clientclosed)

Implements [Client.destroyed](/docs/docs/api/Client.md#clientdestroyed)

### `Pool.stats`
### `BalancedPool.stats`

Returns [`PoolStats`](/docs/docs/api/PoolStats.md) instance for this pool.

Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/docs/docs/api/Cookies.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* **path** `string` (optional)
* **secure** `boolean` (optional)
* **httpOnly** `boolean` (optional)
* **sameSite** `'String'|'Lax'|'None'` (optional)
* **sameSite** `'Strict'|'Lax'|'None'` (optional)
* **unparsed** `string[]` (optional) Left over attributes that weren't parsed.

## `deleteCookie(headers, name[, attributes])`
Expand Down
9 changes: 5 additions & 4 deletions deps/undici/src/docs/docs/api/Dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
* **onResponseData** `(controller: DispatchController, chunk: Buffer) => void` - Invoked when response payload data is received. Not required for `upgrade` requests.
* **onResponseEnd** `(controller: DispatchController, trailers: Record<string, string | string[]>) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests.
* **onResponseError** `(controller: DispatchController, error: Error) => void` - Invoked when an error has occurred. May not throw.
* **onBodySent** `(chunk: Buffer) => void` (optional) - Invoked when a chunk of the request body is sent.

#### Migration from legacy handler API

Expand Down Expand Up @@ -688,7 +689,7 @@ return null

A faster version of `Dispatcher.request`. This method expects the second argument `factory` to return a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable) stream which the response will be written to. This improves performance by avoiding creating an intermediate [`stream.Readable`](https://nodejs.org/api/stream.html#stream_readable_streams) stream when the user expects to directly pipe the response body to a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable) stream.

As demonstrated in [Example 1 - Basic GET stream request](/docs/docs/api/Dispatcher.md#example-1-basic-get-stream-request), it is recommended to use the `option.opaque` property to avoid creating a closure for the `factory` method. This pattern works well with Node.js Web Frameworks such as [Fastify](https://fastify.io). See [Example 2 - Stream to Fastify Response](/docs/docs/api/Dispatch.md#example-2-stream-to-fastify-response) for more details.
As demonstrated in [Example 1 - Basic GET stream request](/docs/docs/api/Dispatcher.md#example-1-basic-get-stream-request), it is recommended to use the `option.opaque` property to avoid creating a closure for the `factory` method. This pattern works well with Node.js Web Frameworks such as [Fastify](https://fastify.io). See [Example 2 - Stream to Fastify Response](/docs/docs/api/Dispatcher.md#example-2-stream-to-fastify-response) for more details.

Arguments:

Expand Down Expand Up @@ -1016,7 +1017,7 @@ The `retry` interceptor allows you to customize the way your dispatcher handles

It accepts the same arguments as the [`RetryHandler` constructor](/docs/docs/api/RetryHandler.md).

**Example - Basic Redirect Interceptor**
**Example - Basic Retry Interceptor**

```js
const { Client, interceptors } = require("undici");
Expand Down Expand Up @@ -1112,7 +1113,7 @@ It represents a storage object for resolved DNS records.
**Example - Basic DNS Interceptor**

```js
const { Client, interceptors } = require("undici");
const { Agent, interceptors } = require("undici");
const { dns } = interceptors;

const client = new Agent().compose([
Expand All @@ -1128,7 +1129,7 @@ const response = await client.request({
**Example - DNS Interceptor and LRU cache as a storage**

```js
const { Client, interceptors } = require("undici");
const { Agent, interceptors } = require("undici");
const QuickLRU = require("quick-lru");
const { dns } = interceptors;

Expand Down
15 changes: 6 additions & 9 deletions deps/undici/src/docs/docs/api/EnvHttpProxyAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ import { setGlobalDispatcher, fetch, EnvHttpProxyAgent } from 'undici'
const envHttpProxyAgent = new EnvHttpProxyAgent()
setGlobalDispatcher(envHttpProxyAgent)

const { status, json } = await fetch('http://localhost:3000/foo')
const response = await fetch('http://localhost:3000/foo')

console.log('response received', status) // response received 200
console.log('response received', response.status) // response received 200

const data = await json() // data { foo: "bar" }
const data = await response.json() // data { foo: "bar" }
```

#### Example - Basic Proxy Request with global agent dispatcher
Expand Down Expand Up @@ -102,14 +102,11 @@ import { EnvHttpProxyAgent, fetch } from 'undici'

const envHttpProxyAgent = new EnvHttpProxyAgent()

const {
status,
json
} = await fetch('http://localhost:3000/foo', { dispatcher: envHttpProxyAgent })
const response = await fetch('http://localhost:3000/foo', { dispatcher: envHttpProxyAgent })

console.log('response received', status) // response received 200
console.log('response received', response.status) // response received 200

const data = await json() // data { foo: "bar" }
const data = await response.json() // data { foo: "bar" }
```

## Instance Methods
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/docs/docs/api/Errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { errors } from 'undici'
| `ResponseError` | `UND_ERR_RESPONSE` | response returned an error status code; carries `statusCode`, `headers` and `body`. |
| `MaxOriginsReachedError` | `UND_ERR_MAX_ORIGINS_REACHED` | the maximum number of allowed origins has been reached. |
| `BalancedPoolMissingUpstreamError` | `UND_ERR_BPL_MISSING_UPSTREAM` | no upstream has been added to the `BalancedPool`. |
| `Socks5ProxyError` | `UND_ERR_SOCKS5*` | an error occurred during SOCKS5 proxy negotiation. |
| `Socks5ProxyError` | `UND_ERR_SOCKS5` | an error occurred during SOCKS5 proxy negotiation. |
| `HTTPParserError` | `HPE_*` | an error occurred while parsing the HTTP response (extends `Error`, not `UndiciError`). |

Be aware of the possible difference between the global dispatcher version and the actual undici version you might be using. We recommend to avoid the check `instanceof errors.UndiciError` and seek for the `error.code === '<error_code>'` instead to avoid inconsistencies.
Expand Down
Loading
Loading