Skip to content

Commit

Permalink
deps: update undici to 7.1.0
Browse files Browse the repository at this point in the history
PR-URL: #56179
Reviewed-By: Rafael Gonzaga <[email protected]>
Reviewed-By: Michaël Zasso <[email protected]>
  • Loading branch information
nodejs-github-bot authored Dec 10, 2024
1 parent 4831423 commit 6c03beb
Show file tree
Hide file tree
Showing 14 changed files with 398 additions and 291 deletions.
2 changes: 2 additions & 0 deletions deps/undici/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,8 @@ and `undici.Agent`) which will enable the family autoselection algorithm when es
* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
* [__Szymon Marczak__](https://github.com/szmarczak), <https://www.npmjs.com/~szmarczak>

## Past Collaborators
* [__Tomas Della Vedova__](https://github.com/delvedor), <https://www.npmjs.com/~delvedor>

### Releasers
Expand Down
13 changes: 11 additions & 2 deletions deps/undici/src/docs/docs/api/Client.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ Returns: `Client`

### Parameter: `ClientOptions`

> ⚠️ Warning: The `H2` support is experimental.
* **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.
* **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.
* **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.
Expand All @@ -34,6 +32,17 @@ Returns: `Client`
* **allowH2**: `boolean` - Default: `false`. Enables support for H2 if the server has assigned bigger priority to it through ALPN negotiation.
* **maxConcurrentStreams**: `number` - Default: `100`. Dictates the maximum number of concurrent streams for a single H2 session. It can be overridden by a SETTINGS remote frame.

> **Notes about HTTP/2**
> - It only works under TLS connections. h2c is not supported.
> - The server must support HTTP/2 and choose it as the protocol during the ALPN negotiation.
> - The server must not have a bigger priority for HTTP/1.1 than HTTP/2.
> - Pseudo headers are automatically attached to the request. If you try to set them, they will be overwritten.
> - The `:path` header is automatically set to the request path.
> - The `:method` header is automatically set to the request method.
> - The `:scheme` header is automatically set to the request scheme.
> - The `:authority` header is automatically set to the request `host[:port]`.
> - `PUSH` frames are yet not supported.
#### Parameter: `ConnectOptions`

Every Tls option, see [here](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
Expand Down
88 changes: 88 additions & 0 deletions deps/undici/src/docs/docs/api/ProxyAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,91 @@ Implements [`Agent.dispatch(options, handlers)`](/docs/docs/api/Agent.md#paramet
### `ProxyAgent.request(options[, callback])`

See [`Dispatcher.request(options [, callback])`](/docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback).


#### Example - ProxyAgent with Fetch

This example demonstrates how to use `fetch` with a proxy via `ProxyAgent`. It is particularly useful for scenarios requiring proxy tunneling.

```javascript
import { ProxyAgent, fetch } from 'undici';

// Define the ProxyAgent
const proxyAgent = new ProxyAgent('http://localhost:8000');

// Make a GET request through the proxy
const response = await fetch('http://localhost:3000/foo', {
dispatcher: proxyAgent,
method: 'GET',
});

console.log('Response status:', response.status);
console.log('Response data:', await response.text());
```

---

#### Example - ProxyAgent with a Custom Proxy Server

This example shows how to create a custom proxy server and use it with `ProxyAgent`.

```javascript
import * as http from 'node:http';
import { createProxy } from 'proxy';
import { ProxyAgent, fetch } from 'undici';

// Create a proxy server
const proxyServer = createProxy(http.createServer());
proxyServer.listen(8000, () => {
console.log('Proxy server running on port 8000');
});

// Define and use the ProxyAgent
const proxyAgent = new ProxyAgent('http://localhost:8000');

const response = await fetch('http://example.com', {
dispatcher: proxyAgent,
method: 'GET',
});

console.log('Response status:', response.status);
console.log('Response data:', await response.text());
```

---

#### Example - ProxyAgent with HTTPS Tunneling

This example demonstrates how to perform HTTPS tunneling using a proxy.

```javascript
import { ProxyAgent, fetch } from 'undici';

// Define a ProxyAgent for HTTPS proxy
const proxyAgent = new ProxyAgent('https://secure.proxy.server');

// Make a request to an HTTPS endpoint via the proxy
const response = await fetch('https://secure.endpoint.com/api/data', {
dispatcher: proxyAgent,
method: 'GET',
});

console.log('Response status:', response.status);
console.log('Response data:', await response.json());
```

#### Example - ProxyAgent as a Global Dispatcher

`ProxyAgent` can be configured as a global dispatcher, making it available for all requests without explicitly passing it. This simplifies code and is useful when a single proxy configuration applies to all requests.

```javascript
import { ProxyAgent, setGlobalDispatcher, fetch } from 'undici';

// Define and configure the ProxyAgent
const proxyAgent = new ProxyAgent('http://localhost:8000');
setGlobalDispatcher(proxyAgent);

// Make requests without specifying the dispatcher
const response = await fetch('http://example.com');
console.log('Response status:', response.status);
console.log('Response data:', await response.text());
7 changes: 4 additions & 3 deletions deps/undici/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ try {
const SqliteCacheStore = require('./lib/cache/sqlite-cache-store')
module.exports.cacheStores.SqliteCacheStore = SqliteCacheStore
} catch (err) {
if (err.code !== 'ERR_UNKNOWN_BUILTIN_MODULE') {
throw err
}
// Most likely node:sqlite was not present, since SqliteCacheStore is
// optional, don't throw. Don't check specific error codes here because while
// ERR_UNKNOWN_BUILTIN_MODULE is expected, users have seen other codes like
// MODULE_NOT_FOUND
}

module.exports.buildConnector = buildConnector
Expand Down
10 changes: 0 additions & 10 deletions deps/undici/src/lib/dispatcher/client-h2.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ const kOpenStreams = Symbol('open streams')

let extractBody

// Experimental
let h2ExperimentalWarned = false

/** @type {import('http2')} */
let http2
try {
Expand Down Expand Up @@ -82,13 +79,6 @@ function parseH2Headers (headers) {
async function connectH2 (client, socket) {
client[kSocket] = socket

if (!h2ExperimentalWarned) {
h2ExperimentalWarned = true
process.emitWarning('H2 support is experimental, expect them to change at any time.', {
code: 'UNDICI-H2'
})
}

const session = http2.connect(client[kUrl], {
createConnection: () => socket,
peerMaxConcurrentStreams: client[kMaxConcurrentStreams],
Expand Down
50 changes: 23 additions & 27 deletions deps/undici/src/lib/handler/decorator-handler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict'

const assert = require('node:assert')
const WrapHandler = require('./wrap-handler')

/**
* @deprecated
Expand All @@ -9,63 +10,58 @@ module.exports = class DecoratorHandler {
#handler
#onCompleteCalled = false
#onErrorCalled = false
#onResponseStartCalled = false

constructor (handler) {
if (typeof handler !== 'object' || handler === null) {
throw new TypeError('handler must be an object')
}
this.#handler = handler
this.#handler = WrapHandler.wrap(handler)
}

onConnect (...args) {
return this.#handler.onConnect?.(...args)
onRequestStart (...args) {
this.#handler.onRequestStart?.(...args)
}

onError (...args) {
this.#onErrorCalled = true
return this.#handler.onError?.(...args)
}

onUpgrade (...args) {
onRequestUpgrade (...args) {
assert(!this.#onCompleteCalled)
assert(!this.#onErrorCalled)

return this.#handler.onUpgrade?.(...args)
return this.#handler.onRequestUpgrade?.(...args)
}

onResponseStarted (...args) {
onResponseStart (...args) {
assert(!this.#onCompleteCalled)
assert(!this.#onErrorCalled)
assert(!this.#onResponseStartCalled)

return this.#handler.onResponseStarted?.(...args)
}

onHeaders (...args) {
assert(!this.#onCompleteCalled)
assert(!this.#onErrorCalled)
this.#onResponseStartCalled = true

return this.#handler.onHeaders?.(...args)
return this.#handler.onResponseStart?.(...args)
}

onData (...args) {
onResponseData (...args) {
assert(!this.#onCompleteCalled)
assert(!this.#onErrorCalled)

return this.#handler.onData?.(...args)
return this.#handler.onResponseData?.(...args)
}

onComplete (...args) {
onResponseEnd (...args) {
assert(!this.#onCompleteCalled)
assert(!this.#onErrorCalled)

this.#onCompleteCalled = true
return this.#handler.onComplete?.(...args)
return this.#handler.onResponseEnd?.(...args)
}

onBodySent (...args) {
assert(!this.#onCompleteCalled)
assert(!this.#onErrorCalled)

return this.#handler.onBodySent?.(...args)
onResponseError (...args) {
this.#onErrorCalled = true
return this.#handler.onResponseError?.(...args)
}

/**
* @deprecated
*/
onBodySent () {}
}
16 changes: 8 additions & 8 deletions deps/undici/src/lib/interceptor/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,27 +222,27 @@ class DNSDispatchHandler extends DecoratorHandler {
#state = null
#opts = null
#dispatch = null
#handler = null
#origin = null
#controller = null

constructor (state, { origin, handler, dispatch }, opts) {
super(handler)
this.#origin = origin
this.#handler = handler
this.#opts = { ...opts }
this.#state = state
this.#dispatch = dispatch
}

onError (err) {
onResponseError (controller, err) {
switch (err.code) {
case 'ETIMEDOUT':
case 'ECONNREFUSED': {
if (this.#state.dualStack) {
// We delete the record and retry
this.#state.runLookup(this.#origin, this.#opts, (err, newOrigin) => {
if (err) {
return this.#handler.onError(err)
super.onResponseError(controller, err)
return
}

const dispatchOpts = {
Expand All @@ -253,18 +253,18 @@ class DNSDispatchHandler extends DecoratorHandler {
this.#dispatch(dispatchOpts, this)
})

// if dual-stack disabled, we error out
return
}

this.#handler.onError(err)
return
// if dual-stack disabled, we error out
super.onResponseError(controller, err)
break
}
case 'ENOTFOUND':
this.#state.deleteRecord(this.#origin)
// eslint-disable-next-line no-fallthrough
default:
this.#handler.onError(err)
super.onResponseError(controller, err)
break
}
}
Expand Down
Loading

0 comments on commit 6c03beb

Please sign in to comment.