Skip to content

Commit

Permalink
deps: update undici to 5.19.1
Browse files Browse the repository at this point in the history
PR-URL: #46634
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
  • Loading branch information
nodejs-github-bot authored and juanarbol committed Feb 15, 2023
1 parent c26a34c commit f0afa0b
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 32 deletions.
3 changes: 2 additions & 1 deletion deps/undici/src/docs/api/MockPool.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ Returns: `MockInterceptor` corresponding to the input options.

We can define the behaviour of an intercepted request with the following options.

* **reply** `(statusCode: number, replyData: string | Buffer | object | MockInterceptor.MockResponseDataHandler, responseOptions?: MockResponseOptions) => MockScope` - define a reply for a matching request. You can define this as a callback to read incoming request data. Default for `responseOptions` is `{}`.
* **reply** `(statusCode: number, replyData: string | Buffer | object | MockInterceptor.MockResponseDataHandler, responseOptions?: MockResponseOptions) => MockScope` - define a reply for a matching request. You can define the replyData as a callback to read incoming request data. Default for `responseOptions` is `{}`.
* **reply** `(callback: MockInterceptor.MockReplyOptionsCallback) => MockScope` - define a reply for a matching request, allowing dynamic mocking of all reply options rather than just the data.
* **replyWithError** `(error: Error) => MockScope` - define an error for a matching request to throw.
* **defaultReplyHeaders** `(headers: Record<string, string>) => MockInterceptor` - define default headers to be included in subsequent replies. These are in addition to headers on a specific reply.
* **defaultReplyTrailers** `(trailers: Record<string, string>) => MockInterceptor` - define default trailers to be included in subsequent replies. These are in addition to trailers on a specific reply.
Expand Down
3 changes: 2 additions & 1 deletion deps/undici/src/lib/cookies/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ function getSetCookies (headers) {
return []
}

return cookies.map((pair) => parseSetCookie(pair[1]))
// In older versions of undici, cookies is a list of name:value.
return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair))
}

/**
Expand Down
3 changes: 3 additions & 0 deletions deps/undici/src/lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ function processHeader (request, key, val) {
key.length === 4 &&
key.toLowerCase() === 'host'
) {
if (headerCharRegex.exec(val) !== null) {
throw new InvalidArgumentError(`invalid ${key} header`)
}
// Consumed by Client
request.host = val
} else if (
Expand Down
23 changes: 20 additions & 3 deletions deps/undici/src/lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,25 +213,42 @@ function parseHeaders (headers, obj = {}) {
for (let i = 0; i < headers.length; i += 2) {
const key = headers[i].toString().toLowerCase()
let val = obj[key]

const encoding = key.length === 19 && key === 'content-disposition'
? 'latin1'
: 'utf8'

if (!val) {
if (Array.isArray(headers[i + 1])) {
obj[key] = headers[i + 1]
} else {
obj[key] = headers[i + 1].toString()
obj[key] = headers[i + 1].toString(encoding)
}
} else {
if (!Array.isArray(val)) {
val = [val]
obj[key] = val
}
val.push(headers[i + 1].toString())
val.push(headers[i + 1].toString(encoding))
}
}
return obj
}

function parseRawHeaders (headers) {
return headers.map(header => header.toString())
const ret = []
for (let n = 0; n < headers.length; n += 2) {
const key = headers[n + 0].toString()

const encoding = key.length === 19 && key.toLowerCase() === 'content-disposition'
? 'latin1'
: 'utf8'

const val = headers[n + 1].toString(encoding)

ret.push(key, val)
}
return ret
}

function isBuffer (buffer) {
Expand Down
83 changes: 71 additions & 12 deletions deps/undici/src/lib/fetch/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const {
isValidHeaderValue
} = require('./util')
const { webidl } = require('./webidl')
const assert = require('assert')

const kHeadersMap = Symbol('headers map')
const kHeadersSortedMap = Symbol('headers map sorted')
Expand All @@ -23,10 +24,12 @@ function headerValueNormalize (potentialValue) {
// To normalize a byte sequence potentialValue, remove
// any leading and trailing HTTP whitespace bytes from
// potentialValue.
return potentialValue.replace(
/^[\r\n\t ]+|[\r\n\t ]+$/g,
''
)

// Trimming the end with `.replace()` and a RegExp is typically subject to
// ReDoS. This is safer and faster.
let i = potentialValue.length
while (/[\r\n\t ]/.test(potentialValue.charAt(--i)));
return potentialValue.slice(0, i + 1).replace(/^[\r\n\t ]+/, '')
}

function fill (headers, object) {
Expand Down Expand Up @@ -115,7 +118,7 @@ class HeadersList {

if (lowercaseName === 'set-cookie') {
this.cookies ??= []
this.cookies.push([name, value])
this.cookies.push(value)
}
}

Expand All @@ -125,7 +128,7 @@ class HeadersList {
const lowercaseName = name.toLowerCase()

if (lowercaseName === 'set-cookie') {
this.cookies = [[name, value]]
this.cookies = [value]
}

// 1. If list contains name, then set the value of
Expand Down Expand Up @@ -383,18 +386,74 @@ class Headers {
return this[kHeadersList].set(name, value)
}

// https://fetch.spec.whatwg.org/#dom-headers-getsetcookie
getSetCookie () {
webidl.brandCheck(this, Headers)

// 1. If this’s header list does not contain `Set-Cookie`, then return « ».
// 2. Return the values of all headers in this’s header list whose name is
// a byte-case-insensitive match for `Set-Cookie`, in order.

const list = this[kHeadersList].cookies

if (list) {
return [...list]
}

return []
}

// https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine
get [kHeadersSortedMap] () {
if (!this[kHeadersList][kHeadersSortedMap]) {
this[kHeadersList][kHeadersSortedMap] = new Map([...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1))
if (this[kHeadersList][kHeadersSortedMap]) {
return this[kHeadersList][kHeadersSortedMap]
}
return this[kHeadersList][kHeadersSortedMap]

// 1. Let headers be an empty list of headers with the key being the name
// and value the value.
const headers = []

// 2. Let names be the result of convert header names to a sorted-lowercase
// set with all the names of the headers in list.
const names = [...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1)
const cookies = this[kHeadersList].cookies

// 3. For each name of names:
for (const [name, value] of names) {
// 1. If name is `set-cookie`, then:
if (name === 'set-cookie') {
// 1. Let values be a list of all values of headers in list whose name
// is a byte-case-insensitive match for name, in order.

// 2. For each value of values:
// 1. Append (name, value) to headers.
for (const value of cookies) {
headers.push([name, value])
}
} else {
// 2. Otherwise:

// 1. Let value be the result of getting name from list.

// 2. Assert: value is non-null.
assert(value !== null)

// 3. Append (name, value) to headers.
headers.push([name, value])
}
}

this[kHeadersList][kHeadersSortedMap] = headers

// 4. Return headers.
return headers
}

keys () {
webidl.brandCheck(this, Headers)

return makeIterator(
() => [...this[kHeadersSortedMap].entries()],
() => [...this[kHeadersSortedMap].values()],
'Headers',
'key'
)
Expand All @@ -404,7 +463,7 @@ class Headers {
webidl.brandCheck(this, Headers)

return makeIterator(
() => [...this[kHeadersSortedMap].entries()],
() => [...this[kHeadersSortedMap].values()],
'Headers',
'value'
)
Expand All @@ -414,7 +473,7 @@ class Headers {
webidl.brandCheck(this, Headers)

return makeIterator(
() => [...this[kHeadersSortedMap].entries()],
() => [...this[kHeadersSortedMap].values()],
'Headers',
'key+value'
)
Expand Down
6 changes: 6 additions & 0 deletions deps/undici/src/lib/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const { getGlobalOrigin } = require('./global')
const { URLSerializer } = require('./dataURL')
const { kHeadersList } = require('../core/symbols')
const assert = require('assert')
const { setMaxListeners, getEventListeners, defaultMaxListeners } = require('events')

let TransformStream = globalThis.TransformStream

Expand Down Expand Up @@ -352,6 +353,11 @@ class Request {
const abort = function () {
acRef.deref()?.abort(this.reason)
}

if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) {
setMaxListeners(100, signal)
}

signal.addEventListener('abort', abort, { once: true })
requestFinalizer.register(this, { signal, abort })
}
Expand Down
6 changes: 5 additions & 1 deletion deps/undici/src/lib/mock/mock-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,11 @@ function buildKey (opts) {
}

function generateKeyValues (data) {
return Object.entries(data).reduce((keyValuePairs, [key, value]) => [...keyValuePairs, key, value], [])
return Object.entries(data).reduce((keyValuePairs, [key, value]) => [
...keyValuePairs,
Buffer.from(`${key}`),
Array.isArray(value) ? value.map(x => Buffer.from(`${x}`)) : Buffer.from(`${value}`)
], [])
}

/**
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "undici",
"version": "5.18.0",
"version": "5.19.1",
"description": "An HTTP/1.1 client, written from scratch for Node.js",
"homepage": "https://undici.nodejs.org",
"bugs": {
Expand Down
2 changes: 2 additions & 0 deletions deps/undici/src/types/connector.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ declare namespace buildConnector {
socketPath?: string | null;
timeout?: number | null;
port?: number;
keepAlive?: boolean | null;
keepAliveInitialDelay?: number | null;
}

export interface Options {
Expand Down
1 change: 1 addition & 0 deletions deps/undici/src/types/fetch.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export declare class Headers implements SpecIterable<[string, string]> {
readonly get: (name: string) => string | null
readonly has: (name: string) => boolean
readonly set: (name: string, value: string) => void
readonly getSetCookie: () => string[]
readonly forEach: (
callbackfn: (value: string, key: string, iterable: Headers) => void,
thisArg?: unknown
Expand Down

0 comments on commit f0afa0b

Please sign in to comment.