Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a7677bc
fs: use signed types for stat data
LiviaMedeiros Jul 18, 2022
b8e5873
src: use named struct instead of typedef
tniessen Jul 18, 2022
cc97a8d
meta: update AUTHORS
nodejs-github-bot Jul 18, 2022
822b9c3
util: add tokens to parseArgs
shadowspawn Jul 18, 2022
3933ce3
deps: update undici to 5.8.0
nodejs-github-bot Jul 18, 2022
d4a0d39
build: add .gitattributes for npm and other shims
hrishikesh-kadam Jul 19, 2022
a88e8e5
tools: update doc to highlight.js@11.6.0
nodejs-github-bot Jul 19, 2022
26c863d
test: ensure NODE_EXTRA_CA_CERTS not set before tests
KrayzeeKev Jul 20, 2022
5b253cc
doc: add security release specifics to releases.md
BethGriggs Jul 14, 2022
d6bc311
doc: mention Win 32-bit openssl build issue
RafaelGSS Jul 15, 2022
df9693d
tools: support versioned node shared libs on z/OS
alexcfyung Mar 8, 2022
bc376c9
tools: add support for using API key to vuln checking script
facutuesca Jul 20, 2022
212115c
child_process: do not need to count length when maxBuffer is Infinity
theanarkh Jul 21, 2022
07c8c4e
http: add drop request event for http server
theanarkh Jul 22, 2022
822fa99
tools: add verbose flag to inactive TSC finder
Trott Jul 22, 2022
e0a8a58
doc: add F3n67u to collaborators
F3n67u Jul 23, 2022
12da85a
doc: fix typo in http.md
airingursb Jul 23, 2022
fc872e5
deps: update hast-util-raw
MoLow Jul 23, 2022
d69b19b
test: simplify ReplStream.wait()
tniessen Jul 23, 2022
687b79a
dns: fix cares memory leak
theanarkh Jul 24, 2022
ad2da1f
dns: fix getServers return undefined
jiahao-si Jul 24, 2022
e297afb
cluster: send connection to other server when worker drop it
theanarkh Jul 24, 2022
a9ab465
stream: fix 0 transform hwm backpressure
ronag Jul 24, 2022
aff813f
util: remove unicode support todo for perf implications
Anemy Jul 24, 2022
34e2c9c
doc: remind backporter about v8_embedder_string
kvakil Jul 24, 2022
7e75216
process: use `defineProperty` instead of assignment
erights Jul 24, 2022
72995c0
meta: update `node-api` in label-pr-config
daeyeon Jul 24, 2022
0ed25c3
doc: fix typo in `src/crypto/README.md`
Jianru-Lin Jul 24, 2022
5cc7554
test: fix test http upload timeout
theanarkh Jul 24, 2022
95dbd86
deps: update corepack to 0.12.1
nodejs-github-bot Jul 24, 2022
ffecb8a
meta: update AUTHORS
nodejs-github-bot Jul 24, 2022
3c077ab
doc: clarify subprocess.stdout/in/err property
cola119 Jul 24, 2022
8339409
test: simplify test-tls-set-secure-context
tniessen Jul 24, 2022
75e60cb
test: work scheduled in process.nextTick can keep the event loop alive
andreubotella Jul 24, 2022
105453b
buffer: do not leak memory if buffer is too big
kvakil Jul 24, 2022
7acbe8f
trace_events: trace net connect event
theanarkh Jul 24, 2022
5e9bdb6
test: remove test-whatwg-events-add-event-listener-options-once.js
F3n67u Jul 24, 2022
e6048b0
inspector: set sampling interval before start
codebytere Jul 25, 2022
b957882
net: fix socket._getpeername
daeyeon Jul 25, 2022
24b4a59
doc: recommend git-node-v8
kvakil Jul 25, 2022
8744e6b
tools: add more options to track flaky tests
aduh95 Jul 25, 2022
122864f
doc: improve documentation for safe `Promise` statics alternatives
aduh95 Jul 25, 2022
7f33433
doc: inspector.close undefined in worker threads
kvakil Jul 16, 2022
23cab44
test: update WPT encoding tests
cola119 Jul 25, 2022
acc68c9
doc: update email and mailmap for BethGriggs
BethGriggs Jul 25, 2022
1073bee
src: pass only Isolate* and env_vars to EnabledDebugList::Parse()
RaisinTen Jul 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
deps: update undici to 5.8.0
PR-URL: #43886
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
  • Loading branch information
nodejs-github-bot authored and targos committed Jul 31, 2022
commit 3933ce3450cc672433dced48290c2699ae93e8bc
15 changes: 8 additions & 7 deletions deps/undici/src/docs/best-practices/proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import { createServer } from 'http'
import proxy from 'proxy'

const server = await buildServer()
const proxy = await buildProxy()
const proxyServer = await buildProxy()

const serverUrl = `http://localhost:${server.address().port}`
const proxyUrl = `http://localhost:${proxy.address().port}`
const proxyUrl = `http://localhost:${proxyServer.address().port}`

server.on('request', (req, res) => {
console.log(req.url) // '/hello?foo=bar'
Expand All @@ -47,7 +47,7 @@ console.log(response.statusCode) // 200
console.log(JSON.parse(data)) // { hello: 'world' }

server.close()
proxy.close()
proxyServer.close()
client.close()

function buildServer () {
Expand All @@ -73,12 +73,12 @@ import { createServer } from 'http'
import proxy from 'proxy'

const server = await buildServer()
const proxy = await buildProxy()
const proxyServer = await buildProxy()

const serverUrl = `http://localhost:${server.address().port}`
const proxyUrl = `http://localhost:${proxy.address().port}`
const proxyUrl = `http://localhost:${proxyServer.address().port}`

proxy.authenticate = function (req, fn) {
proxyServer.authenticate = function (req, fn) {
fn(null, req.headers['proxy-authorization'] === `Basic ${Buffer.from('user:pass').toString('base64')}`)
}

Expand Down Expand Up @@ -107,7 +107,7 @@ console.log(response.statusCode) // 200
console.log(JSON.parse(data)) // { hello: 'world' }

server.close()
proxy.close()
proxyServer.close()
client.close()

function buildServer () {
Expand All @@ -124,3 +124,4 @@ function buildProxy () {
})
}
```

85 changes: 81 additions & 4 deletions deps/undici/src/lib/balanced-pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ const { parseOrigin } = require('./core/util')
const kFactory = Symbol('factory')

const kOptions = Symbol('options')
const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor')
const kCurrentWeight = Symbol('kCurrentWeight')
const kIndex = Symbol('kIndex')
const kWeight = Symbol('kWeight')
const kMaxWeightPerServer = Symbol('kMaxWeightPerServer')
const kErrorPenalty = Symbol('kErrorPenalty')

function getGreatestCommonDivisor (a, b) {
if (b === 0) return a
return getGreatestCommonDivisor(b, a % b)
}

function defaultFactory (origin, opts) {
return new Pool(origin, opts)
Expand All @@ -28,6 +39,11 @@ class BalancedPool extends PoolBase {
super()

this[kOptions] = opts
this[kIndex] = -1
this[kCurrentWeight] = 0

this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100
this[kErrorPenalty] = this[kOptions].errorPenalty || 15

if (!Array.isArray(upstreams)) {
upstreams = [upstreams]
Expand All @@ -42,6 +58,7 @@ class BalancedPool extends PoolBase {
for (const upstream of upstreams) {
this.addUpstream(upstream)
}
this._updateBalancedPoolStats()
}

addUpstream (upstream) {
Expand All @@ -54,12 +71,40 @@ class BalancedPool extends PoolBase {
))) {
return this
}
const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions]))

this[kAddClient](pool)
pool.on('connect', () => {
pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty])
})

pool.on('connectionError', () => {
pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty])
this._updateBalancedPoolStats()
})

pool.on('disconnect', (...args) => {
const err = args[2]
if (err && err.code === 'UND_ERR_SOCKET') {
// decrease the weight of the pool.
pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty])
this._updateBalancedPoolStats()
}
})

for (const client of this[kClients]) {
client[kWeight] = this[kMaxWeightPerServer]
}

this[kAddClient](this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])))
this._updateBalancedPoolStats()

return this
}

_updateBalancedPoolStats () {
this[kGreatestCommonDivisor] = this[kClients].map(p => p[kWeight]).reduce(getGreatestCommonDivisor, 0)
}

removeUpstream (upstream) {
const upstreamOrigin = parseOrigin(upstream).origin

Expand Down Expand Up @@ -100,10 +145,42 @@ class BalancedPool extends PoolBase {
return
}

this[kClients].splice(this[kClients].indexOf(dispatcher), 1)
this[kClients].push(dispatcher)
const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true)

if (allClientsBusy) {
return
}

let counter = 0

let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain])

while (counter++ < this[kClients].length) {
this[kIndex] = (this[kIndex] + 1) % this[kClients].length
const pool = this[kClients][this[kIndex]]

// find pool index with the largest weight
if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) {
maxWeightIndex = this[kIndex]
}

// decrease the current weight every `this[kClients].length`.
if (this[kIndex] === 0) {
// Set the current weight to the next lower weight.
this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor]

if (this[kCurrentWeight] <= 0) {
this[kCurrentWeight] = this[kMaxWeightPerServer]
}
}
if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) {
return pool
}
}

return dispatcher
this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight]
this[kIndex] = maxWeightIndex
return this[kClients][maxWeightIndex]
}
}

Expand Down
29 changes: 29 additions & 0 deletions deps/undici/src/lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ const {
const assert = require('assert')
const util = require('./util')

// tokenRegExp and headerCharRegex have been lifted from
// https://github.com/nodejs/node/blob/main/lib/_http_common.js

/**
* Verifies that the given val is a valid HTTP token
* per the rules defined in RFC 7230
* See https://tools.ietf.org/html/rfc7230#section-3.2.6
*/
const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/

/**
* Matches if val contains an invalid field-vchar
* field-value = *( field-content / obs-fold )
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
* field-vchar = VCHAR / obs-text
*/
const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/

// Verifies that a given path is valid does not contain control chars \x00 to \x20
const invalidPathRegex = /[^\u0021-\u00ff]/

const kHandler = Symbol('handler')

const channels = {}
Expand Down Expand Up @@ -54,10 +75,14 @@ class Request {
method !== 'CONNECT'
) {
throw new InvalidArgumentError('path must be an absolute URL or start with a slash')
} else if (invalidPathRegex.exec(path) !== null) {
throw new InvalidArgumentError('invalid request path')
}

if (typeof method !== 'string') {
throw new InvalidArgumentError('method must be a string')
} else if (tokenRegExp.exec(method) === null) {
throw new InvalidArgumentError('invalid request method')
}

if (upgrade && typeof upgrade !== 'string') {
Expand Down Expand Up @@ -301,6 +326,10 @@ function processHeader (request, key, val) {
key.toLowerCase() === 'expect'
) {
throw new NotSupportedError('expect header not supported')
} else if (tokenRegExp.exec(key) === null) {
throw new InvalidArgumentError('invalid header key')
} else if (headerCharRegex.exec(val) !== null) {
throw new InvalidArgumentError(`invalid ${key} header`)
} else {
request.headers += `${key}: ${val}\r\n`
}
Expand Down
16 changes: 16 additions & 0 deletions deps/undici/src/lib/fetch/body.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ function bodyMixinMethods (instance) {
const chunks = []

for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError('Expected Uint8Array chunk')
}

// Assemble one final large blob with Uint8Array's can exhaust memory.
// That's why we create create multiple blob's and using references
chunks.push(new Blob([chunk]))
Expand All @@ -314,6 +318,10 @@ function bodyMixinMethods (instance) {
let offset = 0

for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError('Expected Uint8Array chunk')
}

buffer.set(chunk, offset)
offset += chunk.length
}
Expand All @@ -331,6 +339,10 @@ function bodyMixinMethods (instance) {
let size = 0

for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError('Expected Uint8Array chunk')
}

chunks.push(chunk)
size += chunk.byteLength
}
Expand All @@ -355,6 +367,10 @@ function bodyMixinMethods (instance) {
const textDecoder = new TextDecoder()

for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError('Expected Uint8Array chunk')
}

result += textDecoder.decode(chunk, { stream: true })
}

Expand Down
3 changes: 2 additions & 1 deletion deps/undici/src/lib/handler/redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ function shouldRemoveHeader (header, removeContent, unknownOrigin) {
return (
(header.length === 4 && header.toString().toLowerCase() === 'host') ||
(removeContent && header.toString().toLowerCase().indexOf('content-') === 0) ||
(unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization')
(unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization') ||
(unknownOrigin && header.length === 6 && header.toString().toLowerCase() === 'cookie')
)
}

Expand Down
3 changes: 2 additions & 1 deletion deps/undici/src/lib/mock/mock-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const {
kOrigin,
kGetNetConnect
} = require('./mock-symbols')
const { buildURL } = require('../core/util')
const { buildURL, nop } = require('../core/util')

function matchValue (match, value) {
if (typeof match === 'string') {
Expand Down Expand Up @@ -288,6 +288,7 @@ function mockDispatch (opts, handler) {
const responseHeaders = generateKeyValues(headers)
const responseTrailers = generateKeyValues(trailers)

handler.abort = nop
handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode))
handler.onData(Buffer.from(responseData))
handler.onComplete(responseTrailers)
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.7.0",
"version": "5.8.0",
"description": "An HTTP/1.1 client, written from scratch for Node.js",
"homepage": "https://undici.nodejs.org",
"bugs": {
Expand Down
25 changes: 24 additions & 1 deletion deps/undici/undici.js
Original file line number Diff line number Diff line change
Expand Up @@ -2227,6 +2227,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
}
const chunks = [];
for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError("Expected Uint8Array chunk");
}
chunks.push(new Blob([chunk]));
}
return new Blob(chunks, { type: this.headers.get("Content-Type") || "" });
Expand All @@ -2241,6 +2244,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
const buffer2 = new Uint8Array(contentLength);
let offset2 = 0;
for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError("Expected Uint8Array chunk");
}
buffer2.set(chunk, offset2);
offset2 += chunk.length;
}
Expand All @@ -2249,6 +2255,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
const chunks = [];
let size = 0;
for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError("Expected Uint8Array chunk");
}
chunks.push(chunk);
size += chunk.byteLength;
}
Expand All @@ -2267,6 +2276,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
let result = "";
const textDecoder = new TextDecoder();
for await (const chunk of consumeBody(this[kState].body)) {
if (!isUint8Array(chunk)) {
throw new TypeError("Expected Uint8Array chunk");
}
result += textDecoder.decode(chunk, { stream: true });
}
result += textDecoder.decode();
Expand Down Expand Up @@ -2350,6 +2362,9 @@ var require_request = __commonJS({
} = require_errors();
var assert = require("assert");
var util = require_util();
var tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
var headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
var invalidPathRegex = /[^\u0021-\u00ff]/;
var kHandler = Symbol("handler");
var channels = {};
var extractBody;
Expand Down Expand Up @@ -2388,9 +2403,13 @@ var require_request = __commonJS({
throw new InvalidArgumentError("path must be a string");
} else if (path[0] !== "/" && !(path.startsWith("http://") || path.startsWith("https://")) && method !== "CONNECT") {
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
} else if (invalidPathRegex.exec(path) !== null) {
throw new InvalidArgumentError("invalid request path");
}
if (typeof method !== "string") {
throw new InvalidArgumentError("method must be a string");
} else if (tokenRegExp.exec(method) === null) {
throw new InvalidArgumentError("invalid request method");
}
if (upgrade && typeof upgrade !== "string") {
throw new InvalidArgumentError("upgrade must be a string");
Expand Down Expand Up @@ -2562,6 +2581,10 @@ var require_request = __commonJS({
throw new InvalidArgumentError("invalid upgrade header");
} else if (key.length === 6 && key.toLowerCase() === "expect") {
throw new NotSupportedError("expect header not supported");
} else if (tokenRegExp.exec(key) === null) {
throw new InvalidArgumentError("invalid header key");
} else if (headerCharRegex.exec(val) !== null) {
throw new InvalidArgumentError(`invalid ${key} header`);
} else {
request.headers += `${key}: ${val}\r
`;
Expand Down Expand Up @@ -2685,7 +2708,7 @@ var require_redirect = __commonJS({
}
}
function shouldRemoveHeader(header, removeContent, unknownOrigin) {
return header.length === 4 && header.toString().toLowerCase() === "host" || removeContent && header.toString().toLowerCase().indexOf("content-") === 0 || unknownOrigin && header.length === 13 && header.toString().toLowerCase() === "authorization";
return header.length === 4 && header.toString().toLowerCase() === "host" || removeContent && header.toString().toLowerCase().indexOf("content-") === 0 || unknownOrigin && header.length === 13 && header.toString().toLowerCase() === "authorization" || unknownOrigin && header.length === 6 && header.toString().toLowerCase() === "cookie";
}
function cleanRequestHeaders(headers, removeContent, unknownOrigin) {
const ret = [];
Expand Down