Skip to content

Commit

Permalink
deps: update undici to 5.17.1
Browse files Browse the repository at this point in the history
PR-URL: #46502
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
nodejs-github-bot committed Feb 7, 2023
1 parent d592630 commit fefaa1c
Show file tree
Hide file tree
Showing 17 changed files with 225 additions and 1,608 deletions.
57 changes: 57 additions & 0 deletions deps/undici/src/docs/api/ContentType.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# MIME Type Parsing

## `MIMEType` interface

* **type** `string`
* **subtype** `string`
* **parameters** `Map<string, string>`
* **essence** `string`

## `parseMIMEType(input)`

Implements [parse a MIME type](https://mimesniff.spec.whatwg.org/#parse-a-mime-type).

Parses a MIME type, returning its type, subtype, and any associated parameters. If the parser can't parse an input it returns the string literal `'failure'`.

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

parseMIMEType('text/html; charset=gbk')
// {
// type: 'text',
// subtype: 'html',
// parameters: Map(1) { 'charset' => 'gbk' },
// essence: 'text/html'
// }
```

Arguments:

* **input** `string`

Returns: `MIMEType|'failure'`

## `serializeAMimeType(input)`

Implements [serialize a MIME type](https://mimesniff.spec.whatwg.org/#serialize-a-mime-type).

Serializes a MIMEType object.

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

serializeAMimeType({
type: 'text',
subtype: 'html',
parameters: new Map([['charset', 'gbk']]),
essence: 'text/html'
})
// text/html;charset=gbk

```

Arguments:

* **mimeType** `MIMEType`

Returns: `string`
14 changes: 7 additions & 7 deletions deps/undici/src/docs/api/Dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Returns: `void | Promise<ConnectData>` - Only returns a `Promise` if no `callbac
#### Parameter: `ConnectData`

* **statusCode** `number`
* **headers** `http.IncomingHttpHeaders`
* **headers** `Record<string, string | string[]>`
* **socket** `stream.Duplex`
* **opaque** `unknown`

Expand Down Expand Up @@ -383,7 +383,7 @@ Extends: [`RequestOptions`](#parameter-requestoptions)
#### Parameter: PipelineHandlerData

* **statusCode** `number`
* **headers** `IncomingHttpHeaders`
* **headers** `Record<string, string | string[]>`
* **opaque** `unknown`
* **body** `stream.Readable`
* **context** `object`
Expand Down Expand Up @@ -477,7 +477,7 @@ The `RequestOptions.method` property should not be value `'CONNECT'`.
#### Parameter: `ResponseData`

* **statusCode** `number`
* **headers** `http.IncomingHttpHeaders` - Note that all header keys are lower-cased, e. g. `content-type`.
* **headers** `Record<string, string | string[]>` - Note that all header keys are lower-cased, e. g. `content-type`.
* **body** `stream.Readable` which also implements [the body mixin from the Fetch Standard](https://fetch.spec.whatwg.org/#body-mixin).
* **trailers** `Record<string, string>` - This object starts out
as empty and will be mutated to contain trailers after `body` has emitted `'end'`.
Expand Down Expand Up @@ -631,7 +631,7 @@ try {

A faster version of `Dispatcher.request`. This method expects the second argument `factory` to return a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable) stream which the response will be written to. This improves performance by avoiding creating an intermediate [`stream.Readable`](https://nodejs.org/api/stream.html#stream_readable_streams) stream when the user expects to directly pipe the response body to a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable) stream.

As demonstrated in [Example 1 - Basic GET stream request](#example-1-basic-get-stream-request), it is recommended to use the `option.opaque` property to avoid creating a closure for the `factory` method. This pattern works well with Node.js Web Frameworks such as [Fastify](https://fastify.io). See [Example 2 - Stream to Fastify Response](#example-2-stream-to-fastify-response) for more details.
As demonstrated in [Example 1 - Basic GET stream request](#example-1---basic-get-stream-request), it is recommended to use the `option.opaque` property to avoid creating a closure for the `factory` method. This pattern works well with Node.js Web Frameworks such as [Fastify](https://fastify.io). See [Example 2 - Stream to Fastify Response](#example-2---stream-to-fastify-response) for more details.

Arguments:

Expand All @@ -644,7 +644,7 @@ Returns: `void | Promise<StreamData>` - Only returns a `Promise` if no `callback
#### Parameter: `StreamFactoryData`

* **statusCode** `number`
* **headers** `http.IncomingHttpHeaders`
* **headers** `Record<string, string | string[]>`
* **opaque** `unknown`
* **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.

Expand Down Expand Up @@ -853,9 +853,9 @@ Emitted when dispatcher is no longer busy.

## Parameter: `UndiciHeaders`

* `http.IncomingHttpHeaders | string[] | null`
* `Record<string, string | string[]> | string[] | null`

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 `http.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.
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.

Keys are lowercase and values are not modified.

Expand Down
1 change: 1 addition & 0 deletions deps/undici/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export * from './types/filereader'
export * from './types/formdata'
export * from './types/diagnostics-channel'
export * from './types/websocket'
export * from './types/content-type'
export { Interceptable } from './types/mock-interceptor'

export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, RedirectHandler, DecoratorHandler }
Expand Down
5 changes: 5 additions & 0 deletions deps/undici/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ if (nodeMajor >= 16) {
module.exports.getCookies = getCookies
module.exports.getSetCookies = getSetCookies
module.exports.setCookie = setCookie

const { parseMIMEType, serializeAMimeType } = require('./lib/fetch/dataURL')

module.exports.parseMIMEType = parseMIMEType
module.exports.serializeAMimeType = serializeAMimeType
}

if (nodeMajor >= 18 && hasCrypto) {
Expand Down
21 changes: 9 additions & 12 deletions deps/undici/src/lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const {
kLocalAddress,
kMaxResponseSize
} = require('./core/symbols')
const FastBuffer = Buffer[Symbol.species]

const kClosedResolve = Symbol('kClosedResolve')

Expand Down Expand Up @@ -362,35 +363,31 @@ async function lazyllhttp () {
},
wasm_on_status: (p, at, len) => {
assert.strictEqual(currentParser.ptr, p)
const start = at - currentBufferPtr
const end = start + len
return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0
const start = at - currentBufferPtr + currentBufferRef.byteOffset
return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
},
wasm_on_message_begin: (p) => {
assert.strictEqual(currentParser.ptr, p)
return currentParser.onMessageBegin() || 0
},
wasm_on_header_field: (p, at, len) => {
assert.strictEqual(currentParser.ptr, p)
const start = at - currentBufferPtr
const end = start + len
return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0
const start = at - currentBufferPtr + currentBufferRef.byteOffset
return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
},
wasm_on_header_value: (p, at, len) => {
assert.strictEqual(currentParser.ptr, p)
const start = at - currentBufferPtr
const end = start + len
return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0
const start = at - currentBufferPtr + currentBufferRef.byteOffset
return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
},
wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {
assert.strictEqual(currentParser.ptr, p)
return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0
},
wasm_on_body: (p, at, len) => {
assert.strictEqual(currentParser.ptr, p)
const start = at - currentBufferPtr
const end = start + len
return currentParser.onBody(currentBufferRef.slice(start, end)) || 0
const start = at - currentBufferPtr + currentBufferRef.byteOffset
return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
},
wasm_on_message_complete: (p) => {
assert.strictEqual(currentParser.ptr, p)
Expand Down
8 changes: 4 additions & 4 deletions deps/undici/src/lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ function processHeaderValue (key, val) {
} else if (headerCharRegex.exec(val) !== null) {
throw new InvalidArgumentError(`invalid ${key} header`)
}

return `${key}: ${val}\r\n`
}

Expand Down Expand Up @@ -313,11 +314,10 @@ function processHeader (request, key, val) {
} else if (
request.contentType === null &&
key.length === 12 &&
key.toLowerCase() === 'content-type' &&
headerCharRegex.exec(val) === null
key.toLowerCase() === 'content-type'
) {
request.contentType = val
request.headers += `${key}: ${val}\r\n`
request.headers += processHeaderValue(key, val)
} else if (
key.length === 17 &&
key.toLowerCase() === 'transfer-encoding'
Expand All @@ -327,7 +327,7 @@ function processHeader (request, key, val) {
key.length === 10 &&
key.toLowerCase() === 'connection'
) {
const value = val.toLowerCase()
const value = typeof val === 'string' ? val.toLowerCase() : null
if (value !== 'close' && value !== 'keep-alive') {
throw new InvalidArgumentError('invalid connection header')
} else if (value === 'close') {
Expand Down
39 changes: 29 additions & 10 deletions deps/undici/src/lib/fetch/dataURL.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ function dataURLProcessor (dataURL) {
// 5. Let mimeType be the result of collecting a
// sequence of code points that are not equal
// to U+002C (,), given position.
let mimeType = collectASequenceOfCodePoints(
(char) => char !== ',',
let mimeType = collectASequenceOfCodePointsFast(
',',
input,
position
)
Expand Down Expand Up @@ -145,6 +145,25 @@ function collectASequenceOfCodePoints (condition, input, position) {
return result
}

/**
* A faster collectASequenceOfCodePoints that only works when comparing a single character.
* @param {string} char
* @param {string} input
* @param {{ position: number }} position
*/
function collectASequenceOfCodePointsFast (char, input, position) {
const idx = input.indexOf(char, position.position)
const start = position.position

if (idx === -1) {
position.position = input.length
return input.slice(start)
}

position.position = idx
return input.slice(start, position.position)
}

// https://url.spec.whatwg.org/#string-percent-decode
/** @param {string} input */
function stringPercentDecode (input) {
Expand Down Expand Up @@ -214,8 +233,8 @@ function parseMIMEType (input) {
// 3. Let type be the result of collecting a sequence
// of code points that are not U+002F (/) from
// input, given position.
const type = collectASequenceOfCodePoints(
(char) => char !== '/',
const type = collectASequenceOfCodePointsFast(
'/',
input,
position
)
Expand All @@ -239,8 +258,8 @@ function parseMIMEType (input) {
// 7. Let subtype be the result of collecting a sequence of
// code points that are not U+003B (;) from input, given
// position.
let subtype = collectASequenceOfCodePoints(
(char) => char !== ';',
let subtype = collectASequenceOfCodePointsFast(
';',
input,
position
)
Expand Down Expand Up @@ -324,8 +343,8 @@ function parseMIMEType (input) {

// 2. Collect a sequence of code points that are not
// U+003B (;) from input, given position.
collectASequenceOfCodePoints(
(char) => char !== ';',
collectASequenceOfCodePointsFast(
';',
input,
position
)
Expand All @@ -335,8 +354,8 @@ function parseMIMEType (input) {
// 1. Set parameterValue to the result of collecting
// a sequence of code points that are not U+003B (;)
// from input, given position.
parameterValue = collectASequenceOfCodePoints(
(char) => char !== ';',
parameterValue = collectASequenceOfCodePointsFast(
';',
input,
position
)
Expand Down
6 changes: 5 additions & 1 deletion deps/undici/src/lib/fetch/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ class HeadersList {

// 2. Append (name, value) to list.
if (exists) {
this[kHeadersMap].set(lowercaseName, { name: exists.name, value: `${exists.value}, ${value}` })
const delimiter = lowercaseName === 'cookie' ? '; ' : ', '
this[kHeadersMap].set(lowercaseName, {
name: exists.name,
value: `${exists.value}${delimiter}${value}`
})
} else {
this[kHeadersMap].set(lowercaseName, { name, value })
}
Expand Down
4 changes: 2 additions & 2 deletions deps/undici/src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "undici",
"version": "5.16.0",
"version": "5.17.1",
"description": "An HTTP/1.1 client, written from scratch for Node.js",
"homepage": "https://undici.nodejs.org",
"bugs": {
Expand Down Expand Up @@ -55,7 +55,7 @@
"test:tdd": "tap test/*.js test/diagnostics-channel/*.js -w",
"test:typescript": "tsd && tsc test/imports/undici-import.ts",
"test:websocket": "node scripts/verifyVersion.js 18 || tap test/websocket/*.js",
"test:wpt": "node scripts/verifyVersion 18 || (node test/wpt/start-fetch.mjs && node test/wpt/start-FileAPI.mjs && node test/wpt/start-mimesniff.mjs && node test/wpt/start-xhr.mjs && node test/wpt/start-websockets.mjs)",
"test:wpt": "node scripts/verifyVersion 18 || (node test/wpt/start-fetch.mjs && node test/wpt/start-FileAPI.mjs && node test/wpt/start-mimesniff.mjs && node test/wpt/start-xhr.mjs && node --no-warnings test/wpt/start-websockets.mjs)",
"coverage": "nyc --reporter=text --reporter=html npm run test",
"coverage:ci": "nyc --reporter=lcov npm run test",
"bench": "PORT=3042 concurrently -k -s first npm:bench:server npm:bench:run",
Expand Down
21 changes: 21 additions & 0 deletions deps/undici/src/types/content-type.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// <reference types="node" />

interface MIMEType {
type: string
subtype: string
parameters: Map<string, string>
essence: string
}

/**
* Parse a string to a {@link MIMEType} object. Returns `failure` if the string
* couldn't be parsed.
* @see https://mimesniff.spec.whatwg.org/#parse-a-mime-type
*/
export function parseMIMEType (input: string): 'failure' | MIMEType

/**
* Convert a MIMEType object to a string.
* @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type
*/
export function serializeAMimeType (mimeType: MIMEType): string
4 changes: 3 additions & 1 deletion deps/undici/src/types/dispatcher.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { URL } from 'url'
import { Duplex, Readable, Writable } from 'stream'
import { EventEmitter } from 'events'
import { IncomingHttpHeaders } from 'http'
import { Blob } from 'buffer'
import { IncomingHttpHeaders } from './header'
import BodyReadable from './readable'
import { FormData } from './formdata'
import Errors from './errors'
Expand Down Expand Up @@ -105,6 +105,8 @@ declare namespace Dispatcher {
query?: Record<string, any>;
/** Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline have completed. Default: `true` if `method` is `HEAD` or `GET`. */
idempotent?: boolean;
/** 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. */
blocking?: boolean;
/** Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`. Default: `method === 'CONNECT' || null`. */
upgrade?: boolean | string | null;
/** The amount of time the parser will wait to receive the complete HTTP headers. Defaults to 30 seconds. */
Expand Down
Loading

0 comments on commit fefaa1c

Please sign in to comment.