Skip to content

Commit

Permalink
deps: update undici to 6.16.1
Browse files Browse the repository at this point in the history
PR-URL: #52948
Reviewed-By: Marco Ippolito <[email protected]>
Reviewed-By: Rafael Gonzaga <[email protected]>
  • Loading branch information
nodejs-github-bot authored and marco-ippolito committed Jul 19, 2024
1 parent b32b62d commit c9c6bf8
Show file tree
Hide file tree
Showing 29 changed files with 1,028 additions and 589 deletions.
162 changes: 162 additions & 0 deletions deps/undici/src/docs/docs/api/EnvHttpProxyAgent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Class: EnvHttpProxyAgent

Stability: Experimental.

Extends: `undici.Dispatcher`

EnvHttpProxyAgent automatically reads the proxy configuration from the environment variables `http_proxy`, `https_proxy`, and `no_proxy` and sets up the proxy agents accordingly. When `http_proxy` and `https_proxy` are set, `http_proxy` is used for HTTP requests and `https_proxy` is used for HTTPS requests. If only `http_proxy` is set, `http_proxy` is used for both HTTP and HTTPS requests. If only `https_proxy` is set, it is only used for HTTPS requests.

`no_proxy` is a comma or space-separated list of hostnames that should not be proxied. The list may contain leading wildcard characters (`*`). If `no_proxy` is set, the EnvHttpProxyAgent will bypass the proxy for requests to hosts that match the list. If `no_proxy` is set to `"*"`, the EnvHttpProxyAgent will bypass the proxy for all requests.

Uppercase environment variables are also supported: `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. However, if both the lowercase and uppercase environment variables are set, the uppercase environment variables will be ignored.

## `new EnvHttpProxyAgent([options])`

Arguments:

* **options** `EnvHttpProxyAgentOptions` (optional) - extends the `Agent` options.

Returns: `EnvHttpProxyAgent`

### Parameter: `EnvHttpProxyAgentOptions`

Extends: [`AgentOptions`](Agent.md#parameter-agentoptions)

* **httpProxy** `string` (optional) - When set, it will override the `HTTP_PROXY` environment variable.
* **httpsProxy** `string` (optional) - When set, it will override the `HTTPS_PROXY` environment variable.
* **noProxy** `string` (optional) - When set, it will override the `NO_PROXY` environment variable.

Examples:

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

const envHttpProxyAgent = new EnvHttpProxyAgent()
// or
const envHttpProxyAgent = new EnvHttpProxyAgent({ httpProxy: 'my.proxy.server:8080', httpsProxy: 'my.proxy.server:8443', noProxy: 'localhost' })
```

#### Example - EnvHttpProxyAgent instantiation

This will instantiate the EnvHttpProxyAgent. It will not do anything until registered as the agent to use with requests.

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

const envHttpProxyAgent = new EnvHttpProxyAgent()
```

#### Example - Basic Proxy Fetch with global agent dispatcher

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

const envHttpProxyAgent = new EnvHttpProxyAgent()
setGlobalDispatcher(envHttpProxyAgent)

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

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

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

#### Example - Basic Proxy Request with global agent dispatcher

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

const envHttpProxyAgent = new EnvHttpProxyAgent()
setGlobalDispatcher(envHttpProxyAgent)

const { statusCode, body } = await request('http://localhost:3000/foo')

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

for await (const data of body) {
console.log('data', data.toString('utf8')) // data foo
}
```

#### Example - Basic Proxy Request with local agent dispatcher

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

const envHttpProxyAgent = new EnvHttpProxyAgent()

const {
statusCode,
body
} = await request('http://localhost:3000/foo', { dispatcher: envHttpProxyAgent })

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

for await (const data of body) {
console.log('data', data.toString('utf8')) // data foo
}
```

#### Example - Basic Proxy Fetch with local agent dispatcher

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

const envHttpProxyAgent = new EnvHttpProxyAgent()

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

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

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

## Instance Methods

### `EnvHttpProxyAgent.close([callback])`

Implements [`Dispatcher.close([callback])`](Dispatcher.md#dispatcherclosecallback-promise).

### `EnvHttpProxyAgent.destroy([error, callback])`

Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).

### `EnvHttpProxyAgent.dispatch(options, handler: AgentDispatchOptions)`

Implements [`Dispatcher.dispatch(options, handler)`](Dispatcher.md#dispatcherdispatchoptions-handler).

#### Parameter: `AgentDispatchOptions`

Extends: [`DispatchOptions`](Dispatcher.md#parameter-dispatchoptions)

* **origin** `string | URL`
* **maxRedirections** `Integer`.

Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).

### `EnvHttpProxyAgent.connect(options[, callback])`

See [`Dispatcher.connect(options[, callback])`](Dispatcher.md#dispatcherconnectoptions-callback).

### `EnvHttpProxyAgent.dispatch(options, handler)`

Implements [`Dispatcher.dispatch(options, handler)`](Dispatcher.md#dispatcherdispatchoptions-handler).

### `EnvHttpProxyAgent.pipeline(options, handler)`

See [`Dispatcher.pipeline(options, handler)`](Dispatcher.md#dispatcherpipelineoptions-handler).

### `EnvHttpProxyAgent.request(options[, callback])`

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

### `EnvHttpProxyAgent.stream(options, factory[, callback])`

See [`Dispatcher.stream(options, factory[, callback])`](Dispatcher.md#dispatcherstreamoptions-factory-callback).

### `EnvHttpProxyAgent.upgrade(options[, callback])`

See [`Dispatcher.upgrade(options[, callback])`](Dispatcher.md#dispatcherupgradeoptions-callback).
4 changes: 2 additions & 2 deletions deps/undici/src/docs/docs/api/Util.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ Receives a header object and returns the parsed value.

Arguments:

- **headers** `Record<string, string | string[]> | (Buffer | string | (Buffer | string)[])[]` (required) - Header object.
- **headers** `(Buffer | string | (Buffer | string)[])[]` (required) - Header object.

- **obj** `Record<string, string | string[]>` (optional) - Object to specify a proxy object. The parsed value is assigned to this object. But, if **headers** is an object, it is not used.

Returns: `Record<string, string | string[]>` If **headers** is an object, it is **headers**. Otherwise, if **obj** is specified, it is equivalent to **obj**.
Returns: `Record<string, string | string[]>` If **obj** is specified, it is equivalent to **obj**.

## `headerNameToString(value)`

Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/docs/docs/best-practices/proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Connecting through a proxy is possible by:

- Using [AgentProxy](../api/ProxyAgent.md).
- Using [ProxyAgent](../api/ProxyAgent.md).
- Configuring `Client` or `Pool` constructor.

The proxy url should be passed to the `Client` or `Pool` constructor, while the upstream server url
Expand Down
66 changes: 49 additions & 17 deletions deps/undici/src/lib/api/api-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

const assert = require('node:assert')
const { Readable } = require('./readable')
const { InvalidArgumentError } = require('../core/errors')
const { InvalidArgumentError, RequestAbortedError } = require('../core/errors')
const util = require('../core/util')
const { getResolveErrorBodyCallback } = require('./util')
const { AsyncResource } = require('node:async_hooks')
const { addSignal, removeSignal } = require('./abort-signal')

class RequestHandler extends AsyncResource {
constructor (opts, callback) {
Expand Down Expand Up @@ -45,6 +44,7 @@ class RequestHandler extends AsyncResource {
throw err
}

this.method = method
this.responseHeaders = responseHeaders || null
this.opaque = opaque || null
this.callback = callback
Expand All @@ -56,14 +56,36 @@ class RequestHandler extends AsyncResource {
this.onInfo = onInfo || null
this.throwOnError = throwOnError
this.highWaterMark = highWaterMark
this.signal = signal
this.reason = null
this.removeAbortListener = null

if (util.isStream(body)) {
body.on('error', (err) => {
this.onError(err)
})
}

addSignal(this, signal)
if (this.signal) {
if (this.signal.aborted) {
this.reason = this.signal.reason ?? new RequestAbortedError()
} else {
this.removeAbortListener = util.addAbortListener(this.signal, () => {
this.reason = this.signal.reason ?? new RequestAbortedError()
if (this.res) {
util.destroy(this.res, this.reason)
} else if (this.abort) {
this.abort(this.reason)
}

if (this.removeAbortListener) {
this.res?.off('close', this.removeAbortListener)
this.removeAbortListener()
this.removeAbortListener = null
}
})
}
}
}

onConnect (abort, context) {
Expand Down Expand Up @@ -93,48 +115,52 @@ class RequestHandler extends AsyncResource {
const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers
const contentType = parsedHeaders['content-type']
const contentLength = parsedHeaders['content-length']
const body = new Readable({ resume, abort, contentType, contentLength, highWaterMark })
const res = new Readable({
resume,
abort,
contentType,
contentLength: this.method !== 'HEAD' && contentLength
? Number(contentLength)
: null,
highWaterMark
})

if (this.removeAbortListener) {
res.on('close', this.removeAbortListener)
}

this.callback = null
this.res = body
this.res = res
if (callback !== null) {
if (this.throwOnError && statusCode >= 400) {
this.runInAsyncScope(getResolveErrorBodyCallback, null,
{ callback, body, contentType, statusCode, statusMessage, headers }
{ callback, body: res, contentType, statusCode, statusMessage, headers }
)
} else {
this.runInAsyncScope(callback, null, null, {
statusCode,
headers,
trailers: this.trailers,
opaque,
body,
body: res,
context
})
}
}
}

onData (chunk) {
const { res } = this
return res.push(chunk)
return this.res.push(chunk)
}

onComplete (trailers) {
const { res } = this

removeSignal(this)

util.parseHeaders(trailers, this.trailers)

res.push(null)
this.res.push(null)
}

onError (err) {
const { res, callback, body, opaque } = this

removeSignal(this)

if (callback) {
// TODO: Does this need queueMicrotask?
this.callback = null
Expand All @@ -155,6 +181,12 @@ class RequestHandler extends AsyncResource {
this.body = null
util.destroy(body, err)
}

if (this.removeAbortListener) {
res?.off('close', this.removeAbortListener)
this.removeAbortListener()
this.removeAbortListener = null
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions deps/undici/src/lib/api/readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ class BodyReadable extends Readable {
// tick as it is created, then a user who is waiting for a
// promise (i.e micro tick) for installing a 'error' listener will
// never get a chance and will always encounter an unhandled exception.
setImmediate(() => {
if (!this[kReading]) {
setImmediate(() => {
callback(err)
})
} else {
callback(err)
})
}
}

on (ev, ...args) {
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/lib/core/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ function setupTimeout (onConnectTimeout, timeout) {
let s1 = null
let s2 = null
const timeoutId = setTimeout(() => {
// setImmediate is added to make sure that we priotorise socket error events over timeouts
// setImmediate is added to make sure that we prioritize socket error events over timeouts
s1 = setImmediate(() => {
if (process.platform === 'win32') {
// Windows needs an extra setImmediate probably due to implementation differences in the socket logic
Expand Down
2 changes: 2 additions & 0 deletions deps/undici/src/lib/dispatcher/client-h2.js
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ function writeH2 (client, request) {
}
} else if (util.isStream(body)) {
writeStream({
abort,
body,
client,
request,
Expand All @@ -535,6 +536,7 @@ function writeH2 (client, request) {
})
} else if (util.isIterable(body)) {
writeIterable({
abort,
body,
client,
request,
Expand Down
Loading

0 comments on commit c9c6bf8

Please sign in to comment.