Skip to content

Commit db93ee4

Browse files
nodejs-github-botjuanarbol
authored andcommitted
deps: update undici to 5.17.1
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>
1 parent b4e49fb commit db93ee4

17 files changed

+225
-1608
lines changed
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# MIME Type Parsing
2+
3+
## `MIMEType` interface
4+
5+
* **type** `string`
6+
* **subtype** `string`
7+
* **parameters** `Map<string, string>`
8+
* **essence** `string`
9+
10+
## `parseMIMEType(input)`
11+
12+
Implements [parse a MIME type](https://mimesniff.spec.whatwg.org/#parse-a-mime-type).
13+
14+
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'`.
15+
16+
```js
17+
import { parseMIMEType } from 'undici'
18+
19+
parseMIMEType('text/html; charset=gbk')
20+
// {
21+
// type: 'text',
22+
// subtype: 'html',
23+
// parameters: Map(1) { 'charset' => 'gbk' },
24+
// essence: 'text/html'
25+
// }
26+
```
27+
28+
Arguments:
29+
30+
* **input** `string`
31+
32+
Returns: `MIMEType|'failure'`
33+
34+
## `serializeAMimeType(input)`
35+
36+
Implements [serialize a MIME type](https://mimesniff.spec.whatwg.org/#serialize-a-mime-type).
37+
38+
Serializes a MIMEType object.
39+
40+
```js
41+
import { serializeAMimeType } from 'undici'
42+
43+
serializeAMimeType({
44+
type: 'text',
45+
subtype: 'html',
46+
parameters: new Map([['charset', 'gbk']]),
47+
essence: 'text/html'
48+
})
49+
// text/html;charset=gbk
50+
51+
```
52+
53+
Arguments:
54+
55+
* **mimeType** `MIMEType`
56+
57+
Returns: `string`

deps/undici/src/docs/api/Dispatcher.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Returns: `void | Promise<ConnectData>` - Only returns a `Promise` if no `callbac
7474
#### Parameter: `ConnectData`
7575

7676
* **statusCode** `number`
77-
* **headers** `http.IncomingHttpHeaders`
77+
* **headers** `Record<string, string | string[]>`
7878
* **socket** `stream.Duplex`
7979
* **opaque** `unknown`
8080

@@ -383,7 +383,7 @@ Extends: [`RequestOptions`](#parameter-requestoptions)
383383
#### Parameter: PipelineHandlerData
384384

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

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

632632
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.
633633

634-
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.
634+
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.
635635

636636
Arguments:
637637

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

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

@@ -853,9 +853,9 @@ Emitted when dispatcher is no longer busy.
853853

854854
## Parameter: `UndiciHeaders`
855855

856-
* `http.IncomingHttpHeaders | string[] | null`
856+
* `Record<string, string | string[]> | string[] | null`
857857

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

860860
Keys are lowercase and values are not modified.
861861

deps/undici/src/index.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export * from './types/filereader'
2323
export * from './types/formdata'
2424
export * from './types/diagnostics-channel'
2525
export * from './types/websocket'
26+
export * from './types/content-type'
2627
export { Interceptable } from './types/mock-interceptor'
2728

2829
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, RedirectHandler, DecoratorHandler }

deps/undici/src/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ if (nodeMajor >= 16) {
134134
module.exports.getCookies = getCookies
135135
module.exports.getSetCookies = getSetCookies
136136
module.exports.setCookie = setCookie
137+
138+
const { parseMIMEType, serializeAMimeType } = require('./lib/fetch/dataURL')
139+
140+
module.exports.parseMIMEType = parseMIMEType
141+
module.exports.serializeAMimeType = serializeAMimeType
137142
}
138143

139144
if (nodeMajor >= 18 && hasCrypto) {

deps/undici/src/lib/client.js

+9-12
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const {
6565
kLocalAddress,
6666
kMaxResponseSize
6767
} = require('./core/symbols')
68+
const FastBuffer = Buffer[Symbol.species]
6869

6970
const kClosedResolve = Symbol('kClosedResolve')
7071

@@ -362,35 +363,31 @@ async function lazyllhttp () {
362363
},
363364
wasm_on_status: (p, at, len) => {
364365
assert.strictEqual(currentParser.ptr, p)
365-
const start = at - currentBufferPtr
366-
const end = start + len
367-
return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0
366+
const start = at - currentBufferPtr + currentBufferRef.byteOffset
367+
return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
368368
},
369369
wasm_on_message_begin: (p) => {
370370
assert.strictEqual(currentParser.ptr, p)
371371
return currentParser.onMessageBegin() || 0
372372
},
373373
wasm_on_header_field: (p, at, len) => {
374374
assert.strictEqual(currentParser.ptr, p)
375-
const start = at - currentBufferPtr
376-
const end = start + len
377-
return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0
375+
const start = at - currentBufferPtr + currentBufferRef.byteOffset
376+
return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
378377
},
379378
wasm_on_header_value: (p, at, len) => {
380379
assert.strictEqual(currentParser.ptr, p)
381-
const start = at - currentBufferPtr
382-
const end = start + len
383-
return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0
380+
const start = at - currentBufferPtr + currentBufferRef.byteOffset
381+
return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
384382
},
385383
wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {
386384
assert.strictEqual(currentParser.ptr, p)
387385
return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0
388386
},
389387
wasm_on_body: (p, at, len) => {
390388
assert.strictEqual(currentParser.ptr, p)
391-
const start = at - currentBufferPtr
392-
const end = start + len
393-
return currentParser.onBody(currentBufferRef.slice(start, end)) || 0
389+
const start = at - currentBufferPtr + currentBufferRef.byteOffset
390+
return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
394391
},
395392
wasm_on_message_complete: (p) => {
396393
assert.strictEqual(currentParser.ptr, p)

deps/undici/src/lib/core/request.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ function processHeaderValue (key, val) {
284284
} else if (headerCharRegex.exec(val) !== null) {
285285
throw new InvalidArgumentError(`invalid ${key} header`)
286286
}
287+
287288
return `${key}: ${val}\r\n`
288289
}
289290

@@ -313,11 +314,10 @@ function processHeader (request, key, val) {
313314
} else if (
314315
request.contentType === null &&
315316
key.length === 12 &&
316-
key.toLowerCase() === 'content-type' &&
317-
headerCharRegex.exec(val) === null
317+
key.toLowerCase() === 'content-type'
318318
) {
319319
request.contentType = val
320-
request.headers += `${key}: ${val}\r\n`
320+
request.headers += processHeaderValue(key, val)
321321
} else if (
322322
key.length === 17 &&
323323
key.toLowerCase() === 'transfer-encoding'
@@ -327,7 +327,7 @@ function processHeader (request, key, val) {
327327
key.length === 10 &&
328328
key.toLowerCase() === 'connection'
329329
) {
330-
const value = val.toLowerCase()
330+
const value = typeof val === 'string' ? val.toLowerCase() : null
331331
if (value !== 'close' && value !== 'keep-alive') {
332332
throw new InvalidArgumentError('invalid connection header')
333333
} else if (value === 'close') {

deps/undici/src/lib/fetch/dataURL.js

+29-10
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ function dataURLProcessor (dataURL) {
3131
// 5. Let mimeType be the result of collecting a
3232
// sequence of code points that are not equal
3333
// to U+002C (,), given position.
34-
let mimeType = collectASequenceOfCodePoints(
35-
(char) => char !== ',',
34+
let mimeType = collectASequenceOfCodePointsFast(
35+
',',
3636
input,
3737
position
3838
)
@@ -145,6 +145,25 @@ function collectASequenceOfCodePoints (condition, input, position) {
145145
return result
146146
}
147147

148+
/**
149+
* A faster collectASequenceOfCodePoints that only works when comparing a single character.
150+
* @param {string} char
151+
* @param {string} input
152+
* @param {{ position: number }} position
153+
*/
154+
function collectASequenceOfCodePointsFast (char, input, position) {
155+
const idx = input.indexOf(char, position.position)
156+
const start = position.position
157+
158+
if (idx === -1) {
159+
position.position = input.length
160+
return input.slice(start)
161+
}
162+
163+
position.position = idx
164+
return input.slice(start, position.position)
165+
}
166+
148167
// https://url.spec.whatwg.org/#string-percent-decode
149168
/** @param {string} input */
150169
function stringPercentDecode (input) {
@@ -214,8 +233,8 @@ function parseMIMEType (input) {
214233
// 3. Let type be the result of collecting a sequence
215234
// of code points that are not U+002F (/) from
216235
// input, given position.
217-
const type = collectASequenceOfCodePoints(
218-
(char) => char !== '/',
236+
const type = collectASequenceOfCodePointsFast(
237+
'/',
219238
input,
220239
position
221240
)
@@ -239,8 +258,8 @@ function parseMIMEType (input) {
239258
// 7. Let subtype be the result of collecting a sequence of
240259
// code points that are not U+003B (;) from input, given
241260
// position.
242-
let subtype = collectASequenceOfCodePoints(
243-
(char) => char !== ';',
261+
let subtype = collectASequenceOfCodePointsFast(
262+
';',
244263
input,
245264
position
246265
)
@@ -324,8 +343,8 @@ function parseMIMEType (input) {
324343

325344
// 2. Collect a sequence of code points that are not
326345
// U+003B (;) from input, given position.
327-
collectASequenceOfCodePoints(
328-
(char) => char !== ';',
346+
collectASequenceOfCodePointsFast(
347+
';',
329348
input,
330349
position
331350
)
@@ -335,8 +354,8 @@ function parseMIMEType (input) {
335354
// 1. Set parameterValue to the result of collecting
336355
// a sequence of code points that are not U+003B (;)
337356
// from input, given position.
338-
parameterValue = collectASequenceOfCodePoints(
339-
(char) => char !== ';',
357+
parameterValue = collectASequenceOfCodePointsFast(
358+
';',
340359
input,
341360
position
342361
)

deps/undici/src/lib/fetch/headers.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ class HeadersList {
104104

105105
// 2. Append (name, value) to list.
106106
if (exists) {
107-
this[kHeadersMap].set(lowercaseName, { name: exists.name, value: `${exists.value}, ${value}` })
107+
const delimiter = lowercaseName === 'cookie' ? '; ' : ', '
108+
this[kHeadersMap].set(lowercaseName, {
109+
name: exists.name,
110+
value: `${exists.value}${delimiter}${value}`
111+
})
108112
} else {
109113
this[kHeadersMap].set(lowercaseName, { name, value })
110114
}

deps/undici/src/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "undici",
3-
"version": "5.16.0",
3+
"version": "5.17.1",
44
"description": "An HTTP/1.1 client, written from scratch for Node.js",
55
"homepage": "https://undici.nodejs.org",
66
"bugs": {
@@ -55,7 +55,7 @@
5555
"test:tdd": "tap test/*.js test/diagnostics-channel/*.js -w",
5656
"test:typescript": "tsd && tsc test/imports/undici-import.ts",
5757
"test:websocket": "node scripts/verifyVersion.js 18 || tap test/websocket/*.js",
58-
"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)",
58+
"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)",
5959
"coverage": "nyc --reporter=text --reporter=html npm run test",
6060
"coverage:ci": "nyc --reporter=lcov npm run test",
6161
"bench": "PORT=3042 concurrently -k -s first npm:bench:server npm:bench:run",
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// <reference types="node" />
2+
3+
interface MIMEType {
4+
type: string
5+
subtype: string
6+
parameters: Map<string, string>
7+
essence: string
8+
}
9+
10+
/**
11+
* Parse a string to a {@link MIMEType} object. Returns `failure` if the string
12+
* couldn't be parsed.
13+
* @see https://mimesniff.spec.whatwg.org/#parse-a-mime-type
14+
*/
15+
export function parseMIMEType (input: string): 'failure' | MIMEType
16+
17+
/**
18+
* Convert a MIMEType object to a string.
19+
* @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type
20+
*/
21+
export function serializeAMimeType (mimeType: MIMEType): string

deps/undici/src/types/dispatcher.d.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { URL } from 'url'
22
import { Duplex, Readable, Writable } from 'stream'
33
import { EventEmitter } from 'events'
4-
import { IncomingHttpHeaders } from 'http'
54
import { Blob } from 'buffer'
5+
import { IncomingHttpHeaders } from './header'
66
import BodyReadable from './readable'
77
import { FormData } from './formdata'
88
import Errors from './errors'
@@ -105,6 +105,8 @@ declare namespace Dispatcher {
105105
query?: Record<string, any>;
106106
/** 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`. */
107107
idempotent?: boolean;
108+
/** 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. */
109+
blocking?: boolean;
108110
/** Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`. Default: `method === 'CONNECT' || null`. */
109111
upgrade?: boolean | string | null;
110112
/** The amount of time the parser will wait to receive the complete HTTP headers. Defaults to 30 seconds. */

0 commit comments

Comments
 (0)