GeezerVison is showing github.com — deps: update undici to 5.20.0 · nodejs/node@cbea56e
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/README.md +12Lines changed: 12 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -405,6 +405,18 @@ implementations in Deno and Cloudflare Workers. | 405 | 405 |
| 406 | 406 | Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling | 407 | 407 |
| | 408 | +## Workarounds | | 409 | + | | 410 | +### Network address family autoselection. | | 411 | + | | 412 | +If you experience problem when connecting to a remote server that is resolved by your DNS servers to a IPv6 (AAAA record) | | 413 | +first, there are chances that your local router or ISP might have problem connecting to IPv6 networks. In that case | | 414 | +undici will throw an error with code `UND_ERR_CONNECT_TIMEOUT`. | | 415 | + | | 416 | +If the target server resolves to both a IPv6 and IPv4 (A records) address and you are using a compatible Node version | | 417 | +(18.3.0 and above), you can fix the problem by providing the `autoSelectFamily` option (support by both `undici.request` | | 418 | +and `undici.Agent`) which will enable the family autoselection algorithm when establishing the connection. | | 419 | + | 408 | 420 | ## Collaborators | 409 | 421 |
| 410 | 422 | * [__Daniele Belardi__](https://github.com/dnlup), <https://www.npmjs.com/~dnlup> | |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/docs/api/Client.md +4-2Lines changed: 4 additions & 2 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -17,8 +17,8 @@ Returns: `Client` | 17 | 17 |
| 18 | 18 | ### Parameter: `ClientOptions` | 19 | 19 |
| 20 | | -* **bodyTimeout** `number | null` (optional) - Default: `30e3` - 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 30 seconds. | 21 | | -* **headersTimeout** `number | null` (optional) - Default: `30e3` - The amount of time the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 30 seconds. | | 20 | +* **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. | | 21 | +* **headersTimeout** `number | null` (optional) - Default: `300e3` - The amount of time the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds. | 22 | 22 | * **keepAliveMaxTimeout** `number | null` (optional) - Default: `600e3` - The maximum allowed `keepAliveTimeout` when overridden by *keep-alive* hints from the server. Defaults to 10 minutes. | 23 | 23 | * **keepAliveTimeout** `number | null` (optional) - Default: `4e3` - The timeout after which a socket without active requests will time out. Monitors time between activity on a connected socket. This value may be overridden by *keep-alive* hints from the server. See [MDN: HTTP - Headers - Keep-Alive directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive#directives) for more details. Defaults to 4 seconds. | 24 | 24 | * **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `1e3` - A number subtracted from server *keep-alive* hints when overriding `keepAliveTimeout` to account for timing inaccuracies caused by e.g. transport latency. Defaults to 1 second. | @@ -28,6 +28,8 @@ Returns: `Client` | 28 | 28 | * **connect** `ConnectOptions | Function | null` (optional) - Default: `null`. | 29 | 29 | * **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body. | 30 | 30 | * **interceptors** `{ Client: DispatchInterceptor[] }` - Default: `[RedirectInterceptor]` - A list of interceptors that are applied to the dispatch method. Additional logic can be applied (such as, but not limited to: 302 status code handling, authentication, cookies, compression and caching). Note that the behavior of interceptors is Experimental and might change at any given time. | | 31 | +* **autoSelectFamily**: `boolean` (optional) - Default: depends on local Node version, on Node 18.13.0 and above is `false`. Enables a family autodetection algorithm that loosely implements section 5 of [RFC 8305](https://tools.ietf.org/html/rfc8305#section-5). See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details. This option is ignored if not supported by the current Node version. | | 32 | +* **autoSelectFamilyAttemptTimeout**: `number` - Default: depends on local Node version, on Node 18.13.0 and above is `250`. The amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details. | 31 | 33 |
| 32 | 34 | #### Parameter: `ConnectOptions` | 33 | 35 |
| |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/docs/api/Dispatcher.md +7-7Lines changed: 7 additions & 7 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -74,7 +74,7 @@ Returns: `void | Promise<ConnectData>` - Only returns a `Promise` if no `callbac | 74 | 74 | #### Parameter: `ConnectData` | 75 | 75 |
| 76 | 76 | * **statusCode** `number` | 77 | | -* **headers** `Record<string, string | string[]>` | | 77 | +* **headers** `Record<string, string | string[] | undefined>` | 78 | 78 | * **socket** `stream.Duplex` | 79 | 79 | * **opaque** `unknown` | 80 | 80 |
| @@ -199,8 +199,8 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo | 199 | 199 | * **idempotent** `boolean` (optional) - Default: `true` if `method` is `'HEAD'` or `'GET'` - Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline has completed. | 200 | 200 | * **blocking** `boolean` (optional) - Default: `false` - Whether the response is expected to take a long time and would end up blocking the pipeline. When this is set to `true` further pipelining will be avoided on the same connection until headers have been received. | 201 | 201 | * **upgrade** `string | null` (optional) - Default: `null` - Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`. | 202 | | -* **bodyTimeout** `number | null` (optional) - 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 30 seconds. | 203 | | -* **headersTimeout** `number | null` (optional) - The amount of time the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 30 seconds. | | 202 | +* **bodyTimeout** `number | null` (optional) - 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. | | 203 | +* **headersTimeout** `number | null` (optional) - The amount of time the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds. | 204 | 204 | * **throwOnError** `boolean` (optional) - Default: `false` - Whether Undici should throw an error upon receiving a 4xx or 5xx response from the server. | 205 | 205 |
| 206 | 206 | #### Parameter: `DispatchHandler` | @@ -383,7 +383,7 @@ Extends: [`RequestOptions`](#parameter-requestoptions) | 383 | 383 | #### Parameter: PipelineHandlerData | 384 | 384 |
| 385 | 385 | * **statusCode** `number` | 386 | | -* **headers** `Record<string, string | string[]>` | | 386 | +* **headers** `Record<string, string | string[] | undefined>` | 387 | 387 | * **opaque** `unknown` | 388 | 388 | * **body** `stream.Readable` | 389 | 389 | * **context** `object` | @@ -644,7 +644,7 @@ Returns: `void | Promise<StreamData>` - Only returns a `Promise` if no `callback | 644 | 644 | #### Parameter: `StreamFactoryData` | 645 | 645 |
| 646 | 646 | * **statusCode** `number` | 647 | | -* **headers** `Record<string, string | string[]>` | | 647 | +* **headers** `Record<string, string | string[] | undefined>` | 648 | 648 | * **opaque** `unknown` | 649 | 649 | * **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received. | 650 | 650 |
| @@ -853,9 +853,9 @@ Emitted when dispatcher is no longer busy. | 853 | 853 |
| 854 | 854 | ## Parameter: `UndiciHeaders` | 855 | 855 |
| 856 | | -* `Record<string, string | string[]> | string[] | null` | | 856 | +* `Record<string, string | string[] | undefined> | string[] | null` | 857 | 857 |
| 858 | | -Header arguments such as `options.headers` in [`Client.dispatch`](Client.md#clientdispatchoptions-handlers) can be specified in two forms; either as an object specified by the `Record<string, string | string[]>` (`IncomingHttpHeaders`) type, or an array of strings. An array representation of a header list must have an even length or an `InvalidArgumentError` will be thrown. | | 858 | +Header arguments such as `options.headers` in [`Client.dispatch`](Client.md#clientdispatchoptions-handlers) can be specified in two forms; either as an object specified by the `Record<string, string | string[] | undefined>` (`IncomingHttpHeaders`) type, or an array of strings. An array representation of a header list must have an even length or an `InvalidArgumentError` will be thrown. | 859 | 859 |
| 860 | 860 | Keys are lowercase and values are not modified. | 861 | 861 |
| |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/index.js +3-7Lines changed: 3 additions & 7 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -20,10 +20,6 @@ const DecoratorHandler = require('./lib/handler/DecoratorHandler') | 20 | 20 | const RedirectHandler = require('./lib/handler/RedirectHandler') | 21 | 21 | const createRedirectInterceptor = require('./lib/interceptor/redirectInterceptor') | 22 | 22 |
| 23 | | -const nodeVersion = process.versions.node.split('.') | 24 | | -const nodeMajor = Number(nodeVersion[0]) | 25 | | -const nodeMinor = Number(nodeVersion[1]) | 26 | | - | 27 | 23 | let hasCrypto | 28 | 24 | try { | 29 | 25 | require('crypto') | @@ -100,7 +96,7 @@ function makeDispatcher (fn) { | 100 | 96 | module.exports.setGlobalDispatcher = setGlobalDispatcher | 101 | 97 | module.exports.getGlobalDispatcher = getGlobalDispatcher | 102 | 98 |
| 103 | | -if (nodeMajor > 16 || (nodeMajor === 16 && nodeMinor >= 8)) { | | 99 | +if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { | 104 | 100 | let fetchImpl = null | 105 | 101 | module.exports.fetch = async function fetch (resource) { | 106 | 102 | if (!fetchImpl) { | @@ -127,7 +123,7 @@ if (nodeMajor > 16 || (nodeMajor === 16 && nodeMinor >= 8)) { | 127 | 123 | module.exports.getGlobalOrigin = getGlobalOrigin | 128 | 124 | } | 129 | 125 |
| 130 | | -if (nodeMajor >= 16) { | | 126 | +if (util.nodeMajor >= 16) { | 131 | 127 | const { deleteCookie, getCookies, getSetCookies, setCookie } = require('./lib/cookies') | 132 | 128 |
| 133 | 129 | module.exports.deleteCookie = deleteCookie | @@ -141,7 +137,7 @@ if (nodeMajor >= 16) { | 141 | 137 | module.exports.serializeAMimeType = serializeAMimeType | 142 | 138 | } | 143 | 139 |
| 144 | | -if (nodeMajor >= 18 && hasCrypto) { | | 140 | +if (util.nodeMajor >= 18 && hasCrypto) { | 145 | 141 | const { WebSocket } = require('./lib/websocket/websocket') | 146 | 142 |
| 147 | 143 | module.exports.WebSocket = WebSocket | |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/client.js +13-3Lines changed: 13 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -109,7 +109,9 @@ class Client extends DispatcherBase { | 109 | 109 | connect, | 110 | 110 | maxRequestsPerClient, | 111 | 111 | localAddress, | 112 | | - maxResponseSize | | 112 | + maxResponseSize, | | 113 | + autoSelectFamily, | | 114 | + autoSelectFamilyAttemptTimeout | 113 | 115 | } = {}) { | 114 | 116 | super() | 115 | 117 |
| @@ -185,12 +187,20 @@ class Client extends DispatcherBase { | 185 | 187 | throw new InvalidArgumentError('maxResponseSize must be a positive number') | 186 | 188 | } | 187 | 189 |
| | 190 | + if ( | | 191 | + autoSelectFamilyAttemptTimeout != null && | | 192 | + (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1) | | 193 | + ) { | | 194 | + throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number') | | 195 | + } | | 196 | + | 188 | 197 | if (typeof connect !== 'function') { | 189 | 198 | connect = buildConnector({ | 190 | 199 | ...tls, | 191 | 200 | maxCachedSessions, | 192 | 201 | socketPath, | 193 | 202 | timeout: connectTimeout, | | 203 | + ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), | 194 | 204 | ...connect | 195 | 205 | }) | 196 | 206 | } | @@ -212,8 +222,8 @@ class Client extends DispatcherBase { | 212 | 222 | this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming | 213 | 223 | this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming | 214 | 224 | this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n` | 215 | | - this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 30e3 | 216 | | - this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 30e3 | | 225 | + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3 | | 226 | + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3 | 217 | 227 | this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength | 218 | 228 | this[kMaxRedirections] = maxRedirections | 219 | 229 | this[kMaxRequests] = maxRequestsPerClient | |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/cookies/parse.js +8-8Lines changed: 8 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 |
| 3 | 3 | const { maxNameValuePairSize, maxAttributeValueSize } = require('./constants') | 4 | 4 | const { isCTLExcludingHtab } = require('./util') | 5 | | -const { collectASequenceOfCodePoints } = require('../fetch/dataURL') | | 5 | +const { collectASequenceOfCodePointsFast } = require('../fetch/dataURL') | 6 | 6 | const assert = require('assert') | 7 | 7 |
| 8 | 8 | /** | @@ -32,7 +32,7 @@ function parseSetCookie (header) { | 32 | 32 | // (including the %x3B (";") in question). | 33 | 33 | const position = { position: 0 } | 34 | 34 |
| 35 | | - nameValuePair = collectASequenceOfCodePoints((char) => char !== ';', header, position) | | 35 | + nameValuePair = collectASequenceOfCodePointsFast(';', header, position) | 36 | 36 | unparsedAttributes = header.slice(position.position) | 37 | 37 | } else { | 38 | 38 | // Otherwise: | @@ -54,8 +54,8 @@ function parseSetCookie (header) { | 54 | 54 | // empty) value string consists of the characters after the first | 55 | 55 | // %x3D ("=") character. | 56 | 56 | const position = { position: 0 } | 57 | | - name = collectASequenceOfCodePoints( | 58 | | - (char) => char !== '=', | | 57 | + name = collectASequenceOfCodePointsFast( | | 58 | + '=', | 59 | 59 | nameValuePair, | 60 | 60 | position | 61 | 61 | ) | @@ -106,8 +106,8 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) | 106 | 106 | if (unparsedAttributes.includes(';')) { | 107 | 107 | // 1. Consume the characters of the unparsed-attributes up to, but | 108 | 108 | // not including, the first %x3B (";") character. | 109 | | - cookieAv = collectASequenceOfCodePoints( | 110 | | - (char) => char !== ';', | | 109 | + cookieAv = collectASequenceOfCodePointsFast( | | 110 | + ';', | 111 | 111 | unparsedAttributes, | 112 | 112 | { position: 0 } | 113 | 113 | ) | @@ -134,8 +134,8 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) | 134 | 134 | // character. | 135 | 135 | const position = { position: 0 } | 136 | 136 |
| 137 | | - attributeName = collectASequenceOfCodePoints( | 138 | | - (char) => char !== '=', | | 137 | + attributeName = collectASequenceOfCodePointsFast( | | 138 | + '=', | 139 | 139 | cookieAv, | 140 | 140 | position | 141 | 141 | ) | |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/core/request.js +1-5Lines changed: 1 addition & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -34,10 +34,6 @@ const channels = {} | 34 | 34 |
| 35 | 35 | let extractBody | 36 | 36 |
| 37 | | -const nodeVersion = process.versions.node.split('.') | 38 | | -const nodeMajor = Number(nodeVersion[0]) | 39 | | -const nodeMinor = Number(nodeVersion[1]) | 40 | | - | 41 | 37 | try { | 42 | 38 | const diagnosticsChannel = require('diagnostics_channel') | 43 | 39 | channels.create = diagnosticsChannel.channel('undici:request:create') | @@ -172,7 +168,7 @@ class Request { | 172 | 168 | } | 173 | 169 |
| 174 | 170 | if (util.isFormDataLike(this.body)) { | 175 | | - if (nodeMajor < 16 || (nodeMajor === 16 && nodeMinor < 8)) { | | 171 | + if (util.nodeMajor < 16 || (util.nodeMajor === 16 && util.nodeMinor < 8)) { | 176 | 172 | throw new InvalidArgumentError('Form-Data bodies are only supported in node v16.8 and newer.') | 177 | 173 | } | 178 | 174 |
| |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/core/util.js +6-1Lines changed: 6 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -10,6 +10,8 @@ const { Blob } = require('buffer') | 10 | 10 | const nodeUtil = require('util') | 11 | 11 | const { stringify } = require('querystring') | 12 | 12 |
| | 13 | +const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v)) | | 14 | + | 13 | 15 | function nop () {} | 14 | 16 |
| 15 | 17 | function isStream (obj) { | @@ -420,5 +422,8 @@ module.exports = { | 420 | 422 | validateHandler, | 421 | 423 | getSocketInfo, | 422 | 424 | isFormDataLike, | 423 | | - buildURL | | 425 | + buildURL, | | 426 | + nodeMajor, | | 427 | + nodeMinor, | | 428 | + nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13) | 424 | 429 | } |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/fetch/dataURL.js +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -556,6 +556,7 @@ module.exports = { | 556 | 556 | dataURLProcessor, | 557 | 557 | URLSerializer, | 558 | 558 | collectASequenceOfCodePoints, | | 559 | + collectASequenceOfCodePointsFast, | 559 | 560 | stringPercentDecode, | 560 | 561 | parseMIMEType, | 561 | 562 | collectAnHTTPQuotedString, | |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/fetch/headers.js +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -75,6 +75,7 @@ class HeadersList { | 75 | 75 | if (init instanceof HeadersList) { | 76 | 76 | this[kHeadersMap] = new Map(init[kHeadersMap]) | 77 | 77 | this[kHeadersSortedMap] = init[kHeadersSortedMap] | | 78 | + this.cookies = init.cookies | 78 | 79 | } else { | 79 | 80 | this[kHeadersMap] = new Map(init) | 80 | 81 | this[kHeadersSortedMap] = null | |
|