Skip to content

Commit

Permalink
deps: update undici to 7.4.0
Browse files Browse the repository at this point in the history
PR-URL: #57236
Reviewed-By: Joyee Cheung <[email protected]>
Reviewed-By: Rafael Gonzaga <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
  • Loading branch information
nodejs-github-bot authored Mar 3, 2025
1 parent 187ddb1 commit 5ac9551
Show file tree
Hide file tree
Showing 19 changed files with 1,580 additions and 294 deletions.
10 changes: 10 additions & 0 deletions deps/undici/src/MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ Maintainers are encouraged to use the extensive and detailed list of labels for
* Issues with a low-barrier of entry should be assigned the `good first issue` label.
* Do not use the `invalid` label, instead use `bug` or `Status: wontfix`.
* Duplicate issues should initially be assigned the `duplicate` label.


## Making a Release

1. Go to github actions, then select ["Create Release PR"](https://github.com/nodejs/undici/actions/workflows/release-create-pr.yml).
2. Run the workflow, selecting `main` and indicating if you want a specific version number or a patch/minor/major release
3. Wait for the PR to be created. Approve the PR ([this](https://github.com/nodejs/undici/pull/4021) is a an example).
4. Land the PR, wait for the CI to pass.
5. Got to the ["Release"](https://github.com/nodejs/undici/actions/workflows/release.yml) workflow, you should see a job waiting.
6. If you are one of the [releases](https://github.com/nodejs/undici?tab=readme-ov-file#releasers), then click "review deployments", then select "release" and click "approve and deploy". If you are not a releaser, contact one.
3 changes: 2 additions & 1 deletion deps/undici/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,8 @@ See [Dispatcher.upgrade](./docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-

* dispatcher `Dispatcher`

Sets the global dispatcher used by Common API Methods.
Sets the global dispatcher used by Common API Methods. Global dispatcher is shared among compatible undici modules,
including undici that is bundled internally with node.js.

### `undici.getGlobalDispatcher()`

Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/docs/docs/api/Dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
* **onResponseStart** `(controller: DispatchController, statusCode: number, headers: Record<string, string | string []>, statusMessage?: string) => void` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests.
* **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** `(error: Error) => void` - Invoked when an error has occurred. May not throw.
* **onResponseError** `(controller: DispatchController, error: Error) => void` - Invoked when an error has occurred. May not throw.

#### Example 1 - Dispatch GET request

Expand Down
2 changes: 0 additions & 2 deletions deps/undici/src/docs/docs/api/EnvHttpProxyAgent.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# 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.
Expand Down
1 change: 1 addition & 0 deletions deps/undici/src/docs/docs/api/Errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { errors } from 'undici'
| `ResponseExceededMaxSizeError` | `UND_ERR_RES_EXCEEDED_MAX_SIZE` | response body exceed the max size allowed |
| `SecureProxyConnectionError` | `UND_ERR_PRX_TLS` | tls connection to a proxy failed |

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.
### `SocketError`

The `SocketError` has a `.socket` property which holds socket metadata:
Expand Down
3 changes: 3 additions & 0 deletions deps/undici/src/index-fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ module.exports.createFastMessageEvent = createFastMessageEvent

module.exports.EventSource = require('./lib/web/eventsource/eventsource').EventSource

const api = require('./lib/api')
const Dispatcher = require('./lib/dispatcher/dispatcher')
Object.assign(Dispatcher.prototype, api)
// Expose the fetch implementation to be enabled in Node.js core via a flag
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
module.exports.getGlobalDispatcher = getGlobalDispatcher
Expand Down
8 changes: 7 additions & 1 deletion deps/undici/src/lib/cache/memory-cache-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ class MemoryCacheStore {
const entry = this.#entries.get(topLevelKey)?.find((entry) => (
entry.deleteAt > now &&
entry.method === key.method &&
(entry.vary == null || Object.keys(entry.vary).every(headerName => entry.vary[headerName] === key.headers?.[headerName]))
(entry.vary == null || Object.keys(entry.vary).every(headerName => {
if (entry.vary[headerName] === null) {
return key.headers[headerName] === undefined
}

return entry.vary[headerName] === key.headers[headerName]
}))
))

return entry == null
Expand Down
23 changes: 11 additions & 12 deletions deps/undici/src/lib/cache/sqlite-cache-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ module.exports = class SqliteCacheStore {
const value = this.#findValue(key)
return value
? {
body: value.body ? Buffer.from(value.body.buffer) : undefined,
body: value.body ? Buffer.from(value.body.buffer, value.body.byteOffset, value.body.byteLength) : undefined,
statusCode: value.statusCode,
statusMessage: value.statusMessage,
headers: value.headers ? JSON.parse(value.headers) : undefined,
Expand Down Expand Up @@ -411,10 +411,6 @@ module.exports = class SqliteCacheStore {
let matches = true

if (value.vary) {
if (!headers) {
return undefined
}

const vary = JSON.parse(value.vary)

for (const header in vary) {
Expand All @@ -440,18 +436,21 @@ module.exports = class SqliteCacheStore {
* @returns {boolean}
*/
function headerValueEquals (lhs, rhs) {
if (lhs == null && rhs == null) {
return true
}

if ((lhs == null && rhs != null) ||
(lhs != null && rhs == null)) {
return false
}

if (Array.isArray(lhs) && Array.isArray(rhs)) {
if (lhs.length !== rhs.length) {
return false
}

for (let i = 0; i < lhs.length; i++) {
if (rhs.includes(lhs[i])) {
return false
}
}

return true
return lhs.every((x, i) => x === rhs[i])
}

return lhs === rhs
Expand Down
9 changes: 0 additions & 9 deletions deps/undici/src/lib/dispatcher/env-http-proxy-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ const DEFAULT_PORTS = {
'https:': 443
}

let experimentalWarned = false

class EnvHttpProxyAgent extends DispatcherBase {
#noProxyValue = null
#noProxyEntries = null
Expand All @@ -21,13 +19,6 @@ class EnvHttpProxyAgent extends DispatcherBase {
super()
this.#opts = opts

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

const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts

this[kNoProxyAgent] = new Agent(agentOpts)
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/lib/llhttp/wasm_build_env.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

> undici@7.3.0 build:wasm
> undici@7.4.0 build:wasm
> node build/wasm.js --docker

> docker run --rm --platform=linux/x86_64 --user 1001:118 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/build/lib/llhttp --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/build,target=/home/node/build/build --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/deps,target=/home/node/build/deps -t ghcr.io/nodejs/wasm-builder@sha256:975f391d907e42a75b8c72eb77c782181e941608687d4d8694c3e9df415a0970 node build/wasm.js
Expand Down
4 changes: 3 additions & 1 deletion deps/undici/src/lib/mock/mock-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ function getResponseData (data) {
return data
} else if (typeof data === 'object') {
return JSON.stringify(data)
} else {
} else if (data) {
return data.toString()
} else {
return ''
}
}

Expand Down
17 changes: 9 additions & 8 deletions deps/undici/src/lib/util/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ function makeCacheKey (opts) {
if (typeof key !== 'string' || typeof val !== 'string') {
throw new Error('opts.headers is not a valid header map')
}
headers[key] = val
headers[key.toLowerCase()] = val
}
} else if (typeof opts.headers === 'object') {
headers = opts.headers
headers = {}

for (const key of Object.keys(opts.headers)) {
headers[key.toLowerCase()] = opts.headers[key]
}
} else {
throw new Error('opts.headers is not an object')
}
Expand Down Expand Up @@ -260,19 +264,16 @@ function parseVaryHeader (varyHeader, headers) {
return headers
}

const output = /** @type {Record<string, string | string[]>} */ ({})
const output = /** @type {Record<string, string | string[] | null>} */ ({})

const varyingHeaders = typeof varyHeader === 'string'
? varyHeader.split(',')
: varyHeader

for (const header of varyingHeaders) {
const trimmedHeader = header.trim().toLowerCase()

if (headers[trimmedHeader]) {
output[trimmedHeader] = headers[trimmedHeader]
} else {
return undefined
}
output[trimmedHeader] = headers[trimmedHeader] ?? null
}

return output
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/lib/web/fetch/body.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ try {
const crypto = require('node:crypto')
random = (max) => crypto.randomInt(0, max)
} catch {
random = (max) => Math.floor(Math.random(max))
random = (max) => Math.floor(Math.random() * max)
}

const textEncoder = new TextEncoder()
Expand Down
21 changes: 12 additions & 9 deletions deps/undici/src/lib/web/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => {

const dependentControllerMap = new WeakMap()

let abortSignalHasEventHandlerLeakWarning

try {
abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0
} catch {
abortSignalHasEventHandlerLeakWarning = false
}

function buildAbort (acRef) {
return abort

Expand Down Expand Up @@ -424,15 +432,10 @@ class Request {
const acRef = new WeakRef(ac)
const abort = buildAbort(acRef)

// Third-party AbortControllers may not work with these.
// See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619.
try {
// If the max amount of listeners is equal to the default, increase it
// This is only available in node >= v19.9.0
if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) {
setMaxListeners(1500, signal)
}
} catch {}
// If the max amount of listeners is equal to the default, increase it
if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal) === defaultMaxListeners) {
setMaxListeners(1500, signal)
}

util.addAbortListener(signal, abort)
// The third argument must be a registry key to be unregistered.
Expand Down
Loading

0 comments on commit 5ac9551

Please sign in to comment.