Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit aac97c2

Browse filesBrowse files
nodejs-github-botdanielleadams
authored andcommitted
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>
1 parent acfc33c commit aac97c2
Copy full SHA for aac97c2

File tree

Expand file treeCollapse file tree

8 files changed

+163
-15
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

8 files changed

+163
-15
lines changed
Open diff view settings
Collapse file

‎deps/undici/src/docs/best-practices/proxy.md‎

Copy file name to clipboardExpand all lines: deps/undici/src/docs/best-practices/proxy.md
+8-7Lines changed: 8 additions & 7 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ import { createServer } from 'http'
2020
import proxy from 'proxy'
2121

2222
const server = await buildServer()
23-
const proxy = await buildProxy()
23+
const proxyServer = await buildProxy()
2424

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

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

4949
server.close()
50-
proxy.close()
50+
proxyServer.close()
5151
client.close()
5252

5353
function buildServer () {
@@ -73,12 +73,12 @@ import { createServer } from 'http'
7373
import proxy from 'proxy'
7474

7575
const server = await buildServer()
76-
const proxy = await buildProxy()
76+
const proxyServer = await buildProxy()
7777

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

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

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

109109
server.close()
110-
proxy.close()
110+
proxyServer.close()
111111
client.close()
112112

113113
function buildServer () {
@@ -124,3 +124,4 @@ function buildProxy () {
124124
})
125125
}
126126
```
127+
Collapse file

‎deps/undici/src/lib/balanced-pool.js‎

Copy file name to clipboardExpand all lines: deps/undici/src/lib/balanced-pool.js
+81-4Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ const { parseOrigin } = require('./core/util')
1818
const kFactory = Symbol('factory')
1919

2020
const kOptions = Symbol('options')
21+
const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor')
22+
const kCurrentWeight = Symbol('kCurrentWeight')
23+
const kIndex = Symbol('kIndex')
24+
const kWeight = Symbol('kWeight')
25+
const kMaxWeightPerServer = Symbol('kMaxWeightPerServer')
26+
const kErrorPenalty = Symbol('kErrorPenalty')
27+
28+
function getGreatestCommonDivisor (a, b) {
29+
if (b === 0) return a
30+
return getGreatestCommonDivisor(b, a % b)
31+
}
2132

2233
function defaultFactory (origin, opts) {
2334
return new Pool(origin, opts)
@@ -28,6 +39,11 @@ class BalancedPool extends PoolBase {
2839
super()
2940

3041
this[kOptions] = opts
42+
this[kIndex] = -1
43+
this[kCurrentWeight] = 0
44+
45+
this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100
46+
this[kErrorPenalty] = this[kOptions].errorPenalty || 15
3147

3248
if (!Array.isArray(upstreams)) {
3349
upstreams = [upstreams]
@@ -42,6 +58,7 @@ class BalancedPool extends PoolBase {
4258
for (const upstream of upstreams) {
4359
this.addUpstream(upstream)
4460
}
61+
this._updateBalancedPoolStats()
4562
}
4663

4764
addUpstream (upstream) {
@@ -54,12 +71,40 @@ class BalancedPool extends PoolBase {
5471
))) {
5572
return this
5673
}
74+
const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions]))
75+
76+
this[kAddClient](pool)
77+
pool.on('connect', () => {
78+
pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty])
79+
})
80+
81+
pool.on('connectionError', () => {
82+
pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty])
83+
this._updateBalancedPoolStats()
84+
})
85+
86+
pool.on('disconnect', (...args) => {
87+
const err = args[2]
88+
if (err && err.code === 'UND_ERR_SOCKET') {
89+
// decrease the weight of the pool.
90+
pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty])
91+
this._updateBalancedPoolStats()
92+
}
93+
})
94+
95+
for (const client of this[kClients]) {
96+
client[kWeight] = this[kMaxWeightPerServer]
97+
}
5798

58-
this[kAddClient](this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])))
99+
this._updateBalancedPoolStats()
59100

60101
return this
61102
}
62103

104+
_updateBalancedPoolStats () {
105+
this[kGreatestCommonDivisor] = this[kClients].map(p => p[kWeight]).reduce(getGreatestCommonDivisor, 0)
106+
}
107+
63108
removeUpstream (upstream) {
64109
const upstreamOrigin = parseOrigin(upstream).origin
65110

@@ -100,10 +145,42 @@ class BalancedPool extends PoolBase {
100145
return
101146
}
102147

103-
this[kClients].splice(this[kClients].indexOf(dispatcher), 1)
104-
this[kClients].push(dispatcher)
148+
const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true)
149+
150+
if (allClientsBusy) {
151+
return
152+
}
153+
154+
let counter = 0
155+
156+
let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain])
157+
158+
while (counter++ < this[kClients].length) {
159+
this[kIndex] = (this[kIndex] + 1) % this[kClients].length
160+
const pool = this[kClients][this[kIndex]]
161+
162+
// find pool index with the largest weight
163+
if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) {
164+
maxWeightIndex = this[kIndex]
165+
}
166+
167+
// decrease the current weight every `this[kClients].length`.
168+
if (this[kIndex] === 0) {
169+
// Set the current weight to the next lower weight.
170+
this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor]
171+
172+
if (this[kCurrentWeight] <= 0) {
173+
this[kCurrentWeight] = this[kMaxWeightPerServer]
174+
}
175+
}
176+
if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) {
177+
return pool
178+
}
179+
}
105180

106-
return dispatcher
181+
this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight]
182+
this[kIndex] = maxWeightIndex
183+
return this[kClients][maxWeightIndex]
107184
}
108185
}
109186

Collapse file

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

Copy file name to clipboardExpand all lines: deps/undici/src/lib/core/request.js
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@ const {
77
const assert = require('assert')
88
const util = require('./util')
99

10+
// tokenRegExp and headerCharRegex have been lifted from
11+
// https://github.com/nodejs/node/blob/main/lib/_http_common.js
12+
13+
/**
14+
* Verifies that the given val is a valid HTTP token
15+
* per the rules defined in RFC 7230
16+
* See https://tools.ietf.org/html/rfc7230#section-3.2.6
17+
*/
18+
const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/
19+
20+
/**
21+
* Matches if val contains an invalid field-vchar
22+
* field-value = *( field-content / obs-fold )
23+
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
24+
* field-vchar = VCHAR / obs-text
25+
*/
26+
const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/
27+
28+
// Verifies that a given path is valid does not contain control chars \x00 to \x20
29+
const invalidPathRegex = /[^\u0021-\u00ff]/
30+
1031
const kHandler = Symbol('handler')
1132

1233
const channels = {}
@@ -54,10 +75,14 @@ class Request {
5475
method !== 'CONNECT'
5576
) {
5677
throw new InvalidArgumentError('path must be an absolute URL or start with a slash')
78+
} else if (invalidPathRegex.exec(path) !== null) {
79+
throw new InvalidArgumentError('invalid request path')
5780
}
5881

5982
if (typeof method !== 'string') {
6083
throw new InvalidArgumentError('method must be a string')
84+
} else if (tokenRegExp.exec(method) === null) {
85+
throw new InvalidArgumentError('invalid request method')
6186
}
6287

6388
if (upgrade && typeof upgrade !== 'string') {
@@ -301,6 +326,10 @@ function processHeader (request, key, val) {
301326
key.toLowerCase() === 'expect'
302327
) {
303328
throw new NotSupportedError('expect header not supported')
329+
} else if (tokenRegExp.exec(key) === null) {
330+
throw new InvalidArgumentError('invalid header key')
331+
} else if (headerCharRegex.exec(val) !== null) {
332+
throw new InvalidArgumentError(`invalid ${key} header`)
304333
} else {
305334
request.headers += `${key}: ${val}\r\n`
306335
}
Collapse file

‎deps/undici/src/lib/fetch/body.js‎

Copy file name to clipboardExpand all lines: deps/undici/src/lib/fetch/body.js
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ function bodyMixinMethods (instance) {
291291
const chunks = []
292292

293293
for await (const chunk of consumeBody(this[kState].body)) {
294+
if (!isUint8Array(chunk)) {
295+
throw new TypeError('Expected Uint8Array chunk')
296+
}
297+
294298
// Assemble one final large blob with Uint8Array's can exhaust memory.
295299
// That's why we create create multiple blob's and using references
296300
chunks.push(new Blob([chunk]))
@@ -314,6 +318,10 @@ function bodyMixinMethods (instance) {
314318
let offset = 0
315319

316320
for await (const chunk of consumeBody(this[kState].body)) {
321+
if (!isUint8Array(chunk)) {
322+
throw new TypeError('Expected Uint8Array chunk')
323+
}
324+
317325
buffer.set(chunk, offset)
318326
offset += chunk.length
319327
}
@@ -331,6 +339,10 @@ function bodyMixinMethods (instance) {
331339
let size = 0
332340

333341
for await (const chunk of consumeBody(this[kState].body)) {
342+
if (!isUint8Array(chunk)) {
343+
throw new TypeError('Expected Uint8Array chunk')
344+
}
345+
334346
chunks.push(chunk)
335347
size += chunk.byteLength
336348
}
@@ -355,6 +367,10 @@ function bodyMixinMethods (instance) {
355367
const textDecoder = new TextDecoder()
356368

357369
for await (const chunk of consumeBody(this[kState].body)) {
370+
if (!isUint8Array(chunk)) {
371+
throw new TypeError('Expected Uint8Array chunk')
372+
}
373+
358374
result += textDecoder.decode(chunk, { stream: true })
359375
}
360376

Collapse file

‎deps/undici/src/lib/handler/redirect.js‎

Copy file name to clipboardExpand all lines: deps/undici/src/lib/handler/redirect.js
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ function shouldRemoveHeader (header, removeContent, unknownOrigin) {
186186
return (
187187
(header.length === 4 && header.toString().toLowerCase() === 'host') ||
188188
(removeContent && header.toString().toLowerCase().indexOf('content-') === 0) ||
189-
(unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization')
189+
(unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization') ||
190+
(unknownOrigin && header.length === 6 && header.toString().toLowerCase() === 'cookie')
190191
)
191192
}
192193

Collapse file

‎deps/undici/src/lib/mock/mock-utils.js‎

Copy file name to clipboardExpand all lines: deps/undici/src/lib/mock/mock-utils.js
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const {
88
kOrigin,
99
kGetNetConnect
1010
} = require('./mock-symbols')
11-
const { buildURL } = require('../core/util')
11+
const { buildURL, nop } = require('../core/util')
1212

1313
function matchValue (match, value) {
1414
if (typeof match === 'string') {
@@ -288,6 +288,7 @@ function mockDispatch (opts, handler) {
288288
const responseHeaders = generateKeyValues(headers)
289289
const responseTrailers = generateKeyValues(trailers)
290290

291+
handler.abort = nop
291292
handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode))
292293
handler.onData(Buffer.from(responseData))
293294
handler.onComplete(responseTrailers)
Collapse file

‎deps/undici/src/package.json‎

Copy file name to clipboardExpand all lines: deps/undici/src/package.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "undici",
3-
"version": "5.7.0",
3+
"version": "5.8.0",
44
"description": "An HTTP/1.1 client, written from scratch for Node.js",
55
"homepage": "https://undici.nodejs.org",
66
"bugs": {
Collapse file

‎deps/undici/undici.js‎

Copy file name to clipboardExpand all lines: deps/undici/undici.js
+24-1Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
22272227
}
22282228
const chunks = [];
22292229
for await (const chunk of consumeBody(this[kState].body)) {
2230+
if (!isUint8Array(chunk)) {
2231+
throw new TypeError("Expected Uint8Array chunk");
2232+
}
22302233
chunks.push(new Blob([chunk]));
22312234
}
22322235
return new Blob(chunks, { type: this.headers.get("Content-Type") || "" });
@@ -2241,6 +2244,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
22412244
const buffer2 = new Uint8Array(contentLength);
22422245
let offset2 = 0;
22432246
for await (const chunk of consumeBody(this[kState].body)) {
2247+
if (!isUint8Array(chunk)) {
2248+
throw new TypeError("Expected Uint8Array chunk");
2249+
}
22442250
buffer2.set(chunk, offset2);
22452251
offset2 += chunk.length;
22462252
}
@@ -2249,6 +2255,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
22492255
const chunks = [];
22502256
let size = 0;
22512257
for await (const chunk of consumeBody(this[kState].body)) {
2258+
if (!isUint8Array(chunk)) {
2259+
throw new TypeError("Expected Uint8Array chunk");
2260+
}
22522261
chunks.push(chunk);
22532262
size += chunk.byteLength;
22542263
}
@@ -2267,6 +2276,9 @@ Content-Type: ${value.type || "application/octet-stream"}\r
22672276
let result = "";
22682277
const textDecoder = new TextDecoder();
22692278
for await (const chunk of consumeBody(this[kState].body)) {
2279+
if (!isUint8Array(chunk)) {
2280+
throw new TypeError("Expected Uint8Array chunk");
2281+
}
22702282
result += textDecoder.decode(chunk, { stream: true });
22712283
}
22722284
result += textDecoder.decode();
@@ -2350,6 +2362,9 @@ var require_request = __commonJS({
23502362
} = require_errors();
23512363
var assert = require("assert");
23522364
var util = require_util();
2365+
var tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
2366+
var headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
2367+
var invalidPathRegex = /[^\u0021-\u00ff]/;
23532368
var kHandler = Symbol("handler");
23542369
var channels = {};
23552370
var extractBody;
@@ -2388,9 +2403,13 @@ var require_request = __commonJS({
23882403
throw new InvalidArgumentError("path must be a string");
23892404
} else if (path[0] !== "/" && !(path.startsWith("http://") || path.startsWith("https://")) && method !== "CONNECT") {
23902405
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
2406+
} else if (invalidPathRegex.exec(path) !== null) {
2407+
throw new InvalidArgumentError("invalid request path");
23912408
}
23922409
if (typeof method !== "string") {
23932410
throw new InvalidArgumentError("method must be a string");
2411+
} else if (tokenRegExp.exec(method) === null) {
2412+
throw new InvalidArgumentError("invalid request method");
23942413
}
23952414
if (upgrade && typeof upgrade !== "string") {
23962415
throw new InvalidArgumentError("upgrade must be a string");
@@ -2562,6 +2581,10 @@ var require_request = __commonJS({
25622581
throw new InvalidArgumentError("invalid upgrade header");
25632582
} else if (key.length === 6 && key.toLowerCase() === "expect") {
25642583
throw new NotSupportedError("expect header not supported");
2584+
} else if (tokenRegExp.exec(key) === null) {
2585+
throw new InvalidArgumentError("invalid header key");
2586+
} else if (headerCharRegex.exec(val) !== null) {
2587+
throw new InvalidArgumentError(`invalid ${key} header`);
25652588
} else {
25662589
request.headers += `${key}: ${val}\r
25672590
`;
@@ -2685,7 +2708,7 @@ var require_redirect = __commonJS({
26852708
}
26862709
}
26872710
function shouldRemoveHeader(header, removeContent, unknownOrigin) {
2688-
return header.length === 4 && header.toString().toLowerCase() === "host" || removeContent && header.toString().toLowerCase().indexOf("content-") === 0 || unknownOrigin && header.length === 13 && header.toString().toLowerCase() === "authorization";
2711+
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";
26892712
}
26902713
function cleanRequestHeaders(headers, removeContent, unknownOrigin) {
26912714
const ret = [];

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.