GeezerVison is showing github.com — deps: update undici to 5.13.0 · nodejs/node@34e708c
File treeExpand file treeCollapse file tree Open diff view settings Some content is hiddenLarge Commits have some content hidden by default. Use the searchbox below for content that may be hidden. Dismiss bannerExpand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/README.md +7-5Lines changed: 7 additions & 5 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -178,10 +178,6 @@ Implements [fetch](https://fetch.spec.whatwg.org/#fetch-method). | 178 | 178 |
| 179 | 179 | Only supported on Node 16.8+. | 180 | 180 |
| 181 | | -This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant with the Fetch Standard. | 182 | | -We plan to ship breaking changes to this feature until it is out of experimental. | 183 | | -Help us improve the test coverage by following instructions at [nodejs/undici/#951](https://github.com/nodejs/undici/issues/951). | 184 | | - | 185 | 181 | Basic usage example: | 186 | 182 |
| 187 | 183 | ```js | @@ -234,9 +230,15 @@ const data = { | 234 | 230 | }, | 235 | 231 | } | 236 | 232 |
| 237 | | -await fetch('https://example.com', { body: data, method: 'POST' }) | | 233 | +await fetch('https://example.com', { body: data, method: 'POST', duplex: 'half' }) | 238 | 234 | ``` | 239 | 235 |
| | 236 | +#### `request.duplex` | | 237 | + | | 238 | +- half | | 239 | + | | 240 | +In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`. And fetch requests are currently always be full duplex. More detail refer to [Fetch Standard.](https://fetch.spec.whatwg.org/#dom-requestinit-duplex) | | 241 | + | 240 | 242 | #### `response.body` | 241 | 243 |
| 242 | 244 | Nodejs has two kinds of streams: [web streams](https://nodejs.org/dist/latest-v16.x/docs/api/webstreams.html), which follow the API of the WHATWG web standard found in browsers, and an older Node-specific [streams API](https://nodejs.org/api/stream.html). `response.body` returns a readable web stream. If you would prefer to work with a Node stream you can convert a web stream using `.fromWeb()`. | |
Collapse file Copy file name to clipboard -28.6 KB
- Display the source diff
- Display the rich diff
Collapse file Copy file name to clipboard +23-23Lines changed: 23 additions & 23 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | | -import Dispatcher = require('./types/dispatcher') | | 1 | +import Dispatcher from'./types/dispatcher' | 2 | 2 | import { setGlobalDispatcher, getGlobalDispatcher } from './types/global-dispatcher' | 3 | 3 | import { setGlobalOrigin, getGlobalOrigin } from './types/global-origin' | 4 | | -import Pool = require('./types/pool') | | 4 | +import Pool from'./types/pool' | 5 | 5 | import { RedirectHandler, DecoratorHandler } from './types/handlers' | 6 | 6 |
| 7 | | -import BalancedPool = require('./types/balanced-pool') | 8 | | -import Client = require('./types/client') | 9 | | -import buildConnector = require('./types/connector') | 10 | | -import errors = require('./types/errors') | 11 | | -import Agent = require('./types/agent') | 12 | | -import MockClient = require('./types/mock-client') | 13 | | -import MockPool = require('./types/mock-pool') | 14 | | -import MockAgent = require('./types/mock-agent') | 15 | | -import mockErrors = require('./types/mock-errors') | 16 | | -import ProxyAgent = require('./types/proxy-agent') | | 7 | +import BalancedPool from './types/balanced-pool' | | 8 | +import Client from'./types/client' | | 9 | +import buildConnector from'./types/connector' | | 10 | +import errors from'./types/errors' | | 11 | +import Agent from'./types/agent' | | 12 | +import MockClient from'./types/mock-client' | | 13 | +import MockPool from'./types/mock-pool' | | 14 | +import MockAgent from'./types/mock-agent' | | 15 | +import mockErrors from'./types/mock-errors' | | 16 | +import ProxyAgent from'./types/proxy-agent' | 17 | 17 | import { request, pipeline, stream, connect, upgrade } from './types/api' | 18 | 18 |
| 19 | 19 | export * from './types/fetch' | @@ -27,26 +27,26 @@ export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, | 27 | 27 | export default Undici | 28 | 28 |
| 29 | 29 | declare namespace Undici { | 30 | | - var Dispatcher: typeof import('./types/dispatcher') | 31 | | - var Pool: typeof import('./types/pool'); | | 30 | + var Dispatcher: typeof import('./types/dispatcher').default | | 31 | + var Pool: typeof import('./types/pool').default; | 32 | 32 | var RedirectHandler: typeof import ('./types/handlers').RedirectHandler | 33 | 33 | var DecoratorHandler: typeof import ('./types/handlers').DecoratorHandler | 34 | 34 | var createRedirectInterceptor: typeof import ('./types/interceptors').createRedirectInterceptor | 35 | | - var BalancedPool: typeof import('./types/balanced-pool'); | 36 | | - var Client: typeof import('./types/client'); | 37 | | - var buildConnector: typeof import('./types/connector'); | 38 | | - var errors: typeof import('./types/errors'); | 39 | | - var Agent: typeof import('./types/agent'); | | 35 | + var BalancedPool: typeof import('./types/balanced-pool').default; | | 36 | + var Client: typeof import('./types/client').default; | | 37 | + var buildConnector: typeof import('./types/connector').default; | | 38 | + var errors: typeof import('./types/errors').default; | | 39 | + var Agent: typeof import('./types/agent').default; | 40 | 40 | var setGlobalDispatcher: typeof import('./types/global-dispatcher').setGlobalDispatcher; | 41 | 41 | var getGlobalDispatcher: typeof import('./types/global-dispatcher').getGlobalDispatcher; | 42 | 42 | var request: typeof import('./types/api').request; | 43 | 43 | var stream: typeof import('./types/api').stream; | 44 | 44 | var pipeline: typeof import('./types/api').pipeline; | 45 | 45 | var connect: typeof import('./types/api').connect; | 46 | 46 | var upgrade: typeof import('./types/api').upgrade; | 47 | | - var MockClient: typeof import('./types/mock-client'); | 48 | | - var MockPool: typeof import('./types/mock-pool'); | 49 | | - var MockAgent: typeof import('./types/mock-agent'); | 50 | | - var mockErrors: typeof import('./types/mock-errors'); | | 47 | + var MockClient: typeof import('./types/mock-client').default; | | 48 | + var MockPool: typeof import('./types/mock-pool').default; | | 49 | + var MockAgent: typeof import('./types/mock-agent').default; | | 50 | + var mockErrors: typeof import('./types/mock-errors').default; | 51 | 51 | var fetch: typeof import('./types/fetch').fetch; | 52 | 52 | } |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/fetch/body.js +18-20Lines changed: 18 additions & 20 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 |
| 3 | 3 | const Busboy = require('busboy') | 4 | 4 | const util = require('../core/util') | 5 | | -const { ReadableStreamFrom, toUSVString, isBlobLike, isReadableStreamLike, readableStreamClose } = require('./util') | | 5 | +const { ReadableStreamFrom, isBlobLike, isReadableStreamLike, readableStreamClose } = require('./util') | 6 | 6 | const { FormData } = require('./formdata') | 7 | 7 | const { kState } = require('./symbols') | 8 | 8 | const { webidl } = require('./webidl') | @@ -66,9 +66,13 @@ function extractBody (object, keepalive = false) { | 66 | 66 | let type = null | 67 | 67 |
| 68 | 68 | // 10. Switch on object: | 69 | | - if (object == null) { | 70 | | - // Note: The IDL processor cannot handle this situation. See | 71 | | - // https://crbug.com/335871. | | 69 | + if (typeof object === 'string') { | | 70 | + // Set source to the UTF-8 encoding of object. | | 71 | + // Note: setting source to a Uint8Array here breaks some mocking assumptions. | | 72 | + source = object | | 73 | + | | 74 | + // Set type to `text/plain;charset=UTF-8`. | | 75 | + type = 'text/plain;charset=UTF-8' | 72 | 76 | } else if (object instanceof URLSearchParams) { | 73 | 77 | // URLSearchParams | 74 | 78 |
| @@ -126,7 +130,8 @@ function extractBody (object, keepalive = false) { | 126 | 130 |
| 127 | 131 | yield * value.stream() | 128 | 132 |
| 129 | | - yield enc.encode('\r\n') | | 133 | + // '\r\n' encoded | | 134 | + yield new Uint8Array([13, 10]) | 130 | 135 | } | 131 | 136 | } | 132 | 137 |
| @@ -157,6 +162,11 @@ function extractBody (object, keepalive = false) { | 157 | 162 | if (object.type) { | 158 | 163 | type = object.type | 159 | 164 | } | | 165 | + } else if (object instanceof Uint8Array) { | | 166 | + // byte sequence | | 167 | + | | 168 | + // Set source to object. | | 169 | + source = object | 160 | 170 | } else if (typeof object[Symbol.asyncIterator] === 'function') { | 161 | 171 | // If keepalive is true, then throw a TypeError. | 162 | 172 | if (keepalive) { | @@ -172,17 +182,10 @@ function extractBody (object, keepalive = false) { | 172 | 182 |
| 173 | 183 | stream = | 174 | 184 | object instanceof ReadableStream ? object : ReadableStreamFrom(object) | 175 | | - } else { | 176 | | - // TODO: byte sequence? | 177 | | - // TODO: scalar value string? | 178 | | - // TODO: else? | 179 | | - source = toUSVString(object) | 180 | | - type = 'text/plain;charset=UTF-8' | 181 | 185 | } | 182 | 186 |
| 183 | 187 | // 11. If source is a byte sequence, then set action to a | 184 | 188 | // step that returns source and length to source’s length. | 185 | | - // TODO: What is a "byte sequence?" | 186 | 189 | if (typeof source === 'string' || util.isBuffer(source)) { | 187 | 190 | length = Buffer.byteLength(source) | 188 | 191 | } | @@ -329,9 +332,7 @@ function bodyMixinMethods (instance) { | 329 | 332 | }, | 330 | 333 |
| 331 | 334 | async formData () { | 332 | | - if (!(this instanceof instance)) { | 333 | | - throw new TypeError('Illegal invocation') | 334 | | - } | | 335 | + webidl.brandCheck(this, instance) | 335 | 336 |
| 336 | 337 | throwIfAborted(this[kState]) | 337 | 338 |
| @@ -433,7 +434,7 @@ function bodyMixinMethods (instance) { | 433 | 434 | throwIfAborted(this[kState]) | 434 | 435 |
| 435 | 436 | // Otherwise, throw a TypeError. | 436 | | - webidl.errors.exception({ | | 437 | + throw webidl.errors.exception({ | 437 | 438 | header: `${instance.name}.formData`, | 438 | 439 | message: 'Could not parse content as FormData.' | 439 | 440 | }) | @@ -450,11 +451,8 @@ function mixinBody (prototype) { | 450 | 451 |
| 451 | 452 | // https://fetch.spec.whatwg.org/#concept-body-consume-body | 452 | 453 | async function specConsumeBody (object, type, instance) { | 453 | | - if (!(object instanceof instance)) { | 454 | | - throw new TypeError('Illegal invocation') | 455 | | - } | | 454 | + webidl.brandCheck(object, instance) | 456 | 455 |
| 457 | | - // TODO: why is this needed? | 458 | 456 | throwIfAborted(object[kState]) | 459 | 457 |
| 460 | 458 | // 1. If object is unusable, then return a promise rejected | |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/fetch/constants.js +19-1Lines changed: 19 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -8,6 +8,17 @@ const nullBodyStatus = [101, 204, 205, 304] | 8 | 8 |
| 9 | 9 | const redirectStatus = [301, 302, 303, 307, 308] | 10 | 10 |
| | 11 | +// https://fetch.spec.whatwg.org/#block-bad-port | | 12 | +const badPorts = [ | | 13 | + '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', | | 14 | + '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', | | 15 | + '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', | | 16 | + '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', | | 17 | + '2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697', | | 18 | + '10080' | | 19 | +] | | 20 | + | | 21 | +// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies | 11 | 22 | const referrerPolicy = [ | 12 | 23 | '', | 13 | 24 | 'no-referrer', | @@ -44,6 +55,11 @@ const requestBodyHeader = [ | 44 | 55 | 'content-type' | 45 | 56 | ] | 46 | 57 |
| | 58 | +// https://fetch.spec.whatwg.org/#enumdef-requestduplex | | 59 | +const requestDuplex = [ | | 60 | + 'half' | | 61 | +] | | 62 | + | 47 | 63 | // http://fetch.spec.whatwg.org/#forbidden-method | 48 | 64 | const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK'] | 49 | 65 |
| @@ -108,5 +124,7 @@ module.exports = { | 108 | 124 | redirectStatus, | 109 | 125 | corsSafeListedMethods, | 110 | 126 | nullBodyStatus, | 111 | | - safeMethods | | 127 | + safeMethods, | | 128 | + badPorts, | | 129 | + requestDuplex | 112 | 130 | } |
Collapse file Copy file name to clipboardExpand all lines: deps/undici/src/lib/fetch/dataURL.js +5-70Lines changed: 5 additions & 70 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | const assert = require('assert') | 2 | 2 | const { atob } = require('buffer') | 3 | | -const { isValidHTTPToken } = require('./util') | | 3 | +const { format } = require('url') | | 4 | +const { isValidHTTPToken, isomorphicDecode } = require('./util') | 4 | 5 |
| 5 | 6 | const encoder = new TextEncoder() | 6 | 7 |
| @@ -54,15 +55,15 @@ function dataURLProcessor (dataURL) { | 54 | 55 | const encodedBody = input.slice(mimeTypeLength + 1) | 55 | 56 |
| 56 | 57 | // 10. Let body be the percent-decoding of encodedBody. | 57 | | - /** @type {Uint8Array|string} */ | 58 | 58 | let body = stringPercentDecode(encodedBody) | 59 | 59 |
| 60 | 60 | // 11. If mimeType ends with U+003B (;), followed by | 61 | 61 | // zero or more U+0020 SPACE, followed by an ASCII | 62 | 62 | // case-insensitive match for "base64", then: | 63 | 63 | if (/;(\u0020){0,}base64$/i.test(mimeType)) { | 64 | 64 | // 1. Let stringBody be the isomorphic decode of body. | 65 | | - const stringBody = decodeURIComponent(new TextDecoder('utf-8').decode(body)) | | 65 | + const stringBody = isomorphicDecode(body) | | 66 | + | 66 | 67 | // 2. Set body to the forgiving-base64 decode of | 67 | 68 | // stringBody. | 68 | 69 | body = forgivingBase64(stringBody) | @@ -111,73 +112,7 @@ function dataURLProcessor (dataURL) { | 111 | 112 | * @param {boolean} excludeFragment | 112 | 113 | */ | 113 | 114 | function URLSerializer (url, excludeFragment = false) { | 114 | | - // 1. Let output be url’s scheme and U+003A (:) concatenated. | 115 | | - let output = url.protocol | 116 | | - | 117 | | - // 2. If url’s host is non-null: | 118 | | - if (url.host.length > 0) { | 119 | | - // 1. Append "//" to output. | 120 | | - output += '//' | 121 | | - | 122 | | - // 2. If url includes credentials, then: | 123 | | - if (url.username.length > 0 || url.password.length > 0) { | 124 | | - // 1. Append url’s username to output. | 125 | | - output += url.username | 126 | | - | 127 | | - // 2. If url’s password is not the empty string, then append U+003A (:), | 128 | | - // followed by url’s password, to output. | 129 | | - if (url.password.length > 0) { | 130 | | - output += ':' + url.password | 131 | | - } | 132 | | - | 133 | | - // 3. Append U+0040 (@) to output. | 134 | | - output += '@' | 135 | | - } | 136 | | - | 137 | | - // 3. Append url’s host, serialized, to output. | 138 | | - output += decodeURIComponent(url.hostname) | 139 | | - | 140 | | - // 4. If url’s port is non-null, append U+003A (:) followed by url’s port, | 141 | | - // serialized, to output. | 142 | | - if (url.port.length > 0) { | 143 | | - output += ':' + url.port | 144 | | - } | 145 | | - } | 146 | | - | 147 | | - // 3. If url’s host is null, url does not have an opaque path, | 148 | | - // url’s path’s size is greater than 1, and url’s path[0] | 149 | | - // is the empty string, then append U+002F (/) followed by | 150 | | - // U+002E (.) to output. | 151 | | - // Note: This prevents web+demo:/.//not-a-host/ or web+demo:/path/..//not-a-host/, | 152 | | - // when parsed and then serialized, from ending up as web+demo://not-a-host/ | 153 | | - // (they end up as web+demo:/.//not-a-host/). | 154 | | - // Undici implementation note: url's path[0] can never be an | 155 | | - // empty string, so we have to slightly alter what the spec says. | 156 | | - if ( | 157 | | - url.host.length === 0 && | 158 | | - url.pathname.length > 1 && | 159 | | - url.href.slice(url.protocol.length + 1)[0] === '.' | 160 | | - ) { | 161 | | - output += '/.' | 162 | | - } | 163 | | - | 164 | | - // 4. Append the result of URL path serializing url to output. | 165 | | - output += url.pathname | 166 | | - | 167 | | - // 5. If url’s query is non-null, append U+003F (?), | 168 | | - // followed by url’s query, to output. | 169 | | - if (url.search.length > 0) { | 170 | | - output += url.search | 171 | | - } | 172 | | - | 173 | | - // 6. If exclude fragment is false and url’s fragment is non-null, | 174 | | - // then append U+0023 (#), followed by url’s fragment, to output. | 175 | | - if (excludeFragment === false && url.hash.length > 0) { | 176 | | - output += url.hash | 177 | | - } | 178 | | - | 179 | | - // 7. Return output. | 180 | | - return output | | 115 | + return format(url, { fragment: !excludeFragment }) | 181 | 116 | } | 182 | 117 |
| 183 | 118 | // https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points | |
|