Skip to content

Commit fb09757

Browse files
Lock file maintenance (#58)
* Lock file maintenance * Update dist file --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeppe Fihl-Pearson <jeppe@tenzer.dk>
1 parent 6f34074 commit fb09757

2 files changed

Lines changed: 127 additions & 36 deletions

File tree

dist/index.js

Lines changed: 124 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5603,6 +5603,9 @@ const EMPTY_BUF = Buffer.alloc(0)
56035603
const FastBuffer = Buffer[Symbol.species]
56045604
const addListener = util.addListener
56055605
const removeAllListeners = util.removeAllListeners
5606+
const kIdleSocketValidation = Symbol('kIdleSocketValidation')
5607+
const kIdleSocketValidationTimeout = Symbol('kIdleSocketValidationTimeout')
5608+
const kSocketUsed = Symbol('kSocketUsed')
56065609

56075610
let extractBody
56085611

@@ -5917,6 +5920,11 @@ class Parser {
59175920
return -1
59185921
}
59195922

5923+
if (client[kRunning] === 0) {
5924+
util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket)))
5925+
return -1
5926+
}
5927+
59205928
const request = client[kQueue][client[kRunningIdx]]
59215929
if (!request) {
59225930
return -1
@@ -6020,6 +6028,11 @@ class Parser {
60206028
return -1
60216029
}
60226030

6031+
if (client[kRunning] === 0) {
6032+
util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket)))
6033+
return -1
6034+
}
6035+
60236036
const request = client[kQueue][client[kRunningIdx]]
60246037

60256038
/* istanbul ignore next: difficult to make a test case for */
@@ -6193,6 +6206,7 @@ class Parser {
61936206
request.onComplete(headers)
61946207

61956208
client[kQueue][client[kRunningIdx]++] = null
6209+
socket[kSocketUsed] = true
61966210

61976211
if (socket[kWriting]) {
61986212
assert(client[kRunning] === 0)
@@ -6251,6 +6265,9 @@ async function connectH1 (client, socket) {
62516265
socket[kWriting] = false
62526266
socket[kReset] = false
62536267
socket[kBlocking] = false
6268+
socket[kIdleSocketValidation] = 0
6269+
socket[kIdleSocketValidationTimeout] = null
6270+
socket[kSocketUsed] = false
62546271
socket[kParser] = new Parser(client, socket, llhttpInstance)
62556272

62566273
addListener(socket, 'error', function (err) {
@@ -6297,6 +6314,8 @@ async function connectH1 (client, socket) {
62976314
const client = this[kClient]
62986315
const parser = this[kParser]
62996316

6317+
clearIdleSocketValidation(this)
6318+
63006319
if (parser) {
63016320
if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) {
63026321
this[kError] = parser.finish() || this[kError]
@@ -6362,7 +6381,7 @@ async function connectH1 (client, socket) {
63626381
return socket.destroyed
63636382
},
63646383
busy (request) {
6365-
if (socket[kWriting] || socket[kReset] || socket[kBlocking]) {
6384+
if (socket[kWriting] || socket[kReset] || socket[kBlocking] || socket[kIdleSocketValidation] === 1) {
63666385
return true
63676386
}
63686387

@@ -6400,6 +6419,31 @@ async function connectH1 (client, socket) {
64006419
}
64016420
}
64026421

6422+
function clearIdleSocketValidation (socket) {
6423+
if (socket[kIdleSocketValidationTimeout]) {
6424+
clearTimeout(socket[kIdleSocketValidationTimeout])
6425+
socket[kIdleSocketValidationTimeout] = null
6426+
}
6427+
6428+
socket[kIdleSocketValidation] = 0
6429+
}
6430+
6431+
function scheduleIdleSocketValidation (client, socket) {
6432+
socket[kIdleSocketValidation] = 1
6433+
socket[kIdleSocketValidationTimeout] = setTimeout(() => {
6434+
socket[kIdleSocketValidationTimeout] = null
6435+
socket[kIdleSocketValidation] = 2
6436+
6437+
if (client[kSocket] === socket && !socket.destroyed) {
6438+
client[kResume]()
6439+
}
6440+
}, 0)
6441+
socket[kIdleSocketValidationTimeout].unref?.()
6442+
}
6443+
6444+
/**
6445+
* @param {import('./client.js')} client
6446+
*/
64036447
function resumeH1 (client) {
64046448
const socket = client[kSocket]
64056449

@@ -6414,6 +6458,32 @@ function resumeH1 (client) {
64146458
socket[kNoRef] = false
64156459
}
64166460

6461+
if (client[kRunning] === 0 && client[kPending] > 0 && socket[kSocketUsed]) {
6462+
if (socket[kIdleSocketValidation] === 0) {
6463+
scheduleIdleSocketValidation(client, socket)
6464+
socket[kParser].readMore()
6465+
if (socket.destroyed) {
6466+
return
6467+
}
6468+
return
6469+
}
6470+
6471+
if (socket[kIdleSocketValidation] === 1) {
6472+
socket[kParser].readMore()
6473+
if (socket.destroyed) {
6474+
return
6475+
}
6476+
return
6477+
}
6478+
}
6479+
6480+
if (client[kRunning] === 0) {
6481+
socket[kParser].readMore()
6482+
if (socket.destroyed) {
6483+
return
6484+
}
6485+
}
6486+
64176487
if (client[kSize] === 0) {
64186488
if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) {
64196489
socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE)
@@ -6507,6 +6577,7 @@ function writeH1 (client, request) {
65076577
}
65086578

65096579
const socket = client[kSocket]
6580+
clearIdleSocketValidation(socket)
65106581

65116582
const abort = (err) => {
65126583
if (request.aborted || request.completed) {
@@ -8376,6 +8447,7 @@ class DispatcherBase extends Dispatcher {
83768447

83778448
get webSocketOptions () {
83788449
return {
8450+
maxFragments: this[kWebSocketOptions].maxFragments ?? 131072,
83798451
maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024
83808452
}
83818453
}
@@ -14275,32 +14347,25 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
1427514347
// If the attribute-name case-insensitively matches the string
1427614348
// "SameSite", the user agent MUST process the cookie-av as follows:
1427714349

14278-
// 1. Let enforcement be "Default".
14279-
let enforcement = 'Default'
14280-
1428114350
const attributeValueLowercase = attributeValue.toLowerCase()
14282-
// 2. If cookie-av's attribute-value is a case-insensitive match for
14283-
// "None", set enforcement to "None".
14284-
if (attributeValueLowercase.includes('none')) {
14285-
enforcement = 'None'
14286-
}
1428714351

14288-
// 3. If cookie-av's attribute-value is a case-insensitive match for
14289-
// "Strict", set enforcement to "Strict".
14290-
if (attributeValueLowercase.includes('strict')) {
14291-
enforcement = 'Strict'
14352+
// 1. If cookie-av's attribute-value is a case-insensitive match for
14353+
// "None", append an attribute to the cookie-attribute-list with an
14354+
// attribute-name of "SameSite" and an attribute-value of "None".
14355+
if (attributeValueLowercase === 'none') {
14356+
cookieAttributeList.sameSite = 'None'
14357+
} else if (attributeValueLowercase === 'strict') {
14358+
// 2. If cookie-av's attribute-value is a case-insensitive match for
14359+
// "Strict", append an attribute to the cookie-attribute-list with
14360+
// an attribute-name of "SameSite" and an attribute-value of
14361+
// "Strict".
14362+
cookieAttributeList.sameSite = 'Strict'
14363+
} else if (attributeValueLowercase === 'lax') {
14364+
// 3. If cookie-av's attribute-value is a case-insensitive match for
14365+
// "Lax", append an attribute to the cookie-attribute-list with an
14366+
// attribute-name of "SameSite" and an attribute-value of "Lax".
14367+
cookieAttributeList.sameSite = 'Lax'
1429214368
}
14293-
14294-
// 4. If cookie-av's attribute-value is a case-insensitive match for
14295-
// "Lax", set enforcement to "Lax".
14296-
if (attributeValueLowercase.includes('lax')) {
14297-
enforcement = 'Lax'
14298-
}
14299-
14300-
// 5. Append an attribute to the cookie-attribute-list with an
14301-
// attribute-name of "SameSite" and an attribute-value of
14302-
// enforcement.
14303-
cookieAttributeList.sameSite = enforcement
1430414369
} else {
1430514370
cookieAttributeList.unparsed ??= []
1430614371

@@ -27096,6 +27161,11 @@ const { closeWebSocketConnection } = __nccwpck_require__(6897)
2709627161
const { PerMessageDeflate } = __nccwpck_require__(9469)
2709727162
const { MessageSizeExceededError } = __nccwpck_require__(8707)
2709827163

27164+
function failWebsocketConnectionWithCode (ws, code, reason) {
27165+
closeWebSocketConnection(ws, code, reason, Buffer.byteLength(reason))
27166+
failWebsocketConnection(ws, reason)
27167+
}
27168+
2709927169
// This code was influenced by ws released under the MIT license.
2710027170
// Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
2710127171
// Copyright (c) 2013 Arnout Kazemier and contributors
@@ -27115,19 +27185,23 @@ class ByteParser extends Writable {
2711527185
/** @type {Map<string, PerMessageDeflate>} */
2711627186
#extensions
2711727187

27188+
/** @type {number} */
27189+
#maxFragments
27190+
2711827191
/** @type {number} */
2711927192
#maxPayloadSize
2712027193

2712127194
/**
2712227195
* @param {import('./websocket').WebSocket} ws
2712327196
* @param {Map<string, string>|null} extensions
27124-
* @param {{ maxPayloadSize?: number }} [options]
27197+
* @param {{ maxFragments?: number, maxPayloadSize?: number }} [options]
2712527198
*/
2712627199
constructor (ws, extensions, options = {}) {
2712727200
super()
2712827201

2712927202
this.ws = ws
2713027203
this.#extensions = extensions == null ? new Map() : extensions
27204+
this.#maxFragments = options.maxFragments ?? 0
2713127205
this.#maxPayloadSize = options.maxPayloadSize ?? 0
2713227206

2713327207
if (this.#extensions.has('permessage-deflate')) {
@@ -27151,9 +27225,9 @@ class ByteParser extends Writable {
2715127225
if (
2715227226
this.#maxPayloadSize > 0 &&
2715327227
!isControlFrame(this.#info.opcode) &&
27154-
this.#info.payloadLength > this.#maxPayloadSize
27228+
this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize
2715527229
) {
27156-
failWebsocketConnection(this.ws, 'Payload size exceeds maximum allowed size')
27230+
failWebsocketConnectionWithCode(this.ws, 1009, 'Payload size exceeds maximum allowed size')
2715727231
return false
2715827232
}
2715927233

@@ -27318,10 +27392,12 @@ class ByteParser extends Writable {
2731827392
this.#state = parserStates.INFO
2731927393
} else {
2732027394
if (!this.#info.compressed) {
27321-
this.writeFragments(body)
27395+
if (!this.writeFragments(body)) {
27396+
return
27397+
}
2732227398

2732327399
if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
27324-
failWebsocketConnection(this.ws, new MessageSizeExceededError().message)
27400+
failWebsocketConnectionWithCode(this.ws, 1009, new MessageSizeExceededError().message)
2732527401
return
2732627402
}
2732727403

@@ -27340,14 +27416,17 @@ class ByteParser extends Writable {
2734027416
this.#info.fin,
2734127417
(error, data) => {
2734227418
if (error) {
27343-
failWebsocketConnection(this.ws, error.message)
27419+
const code = error instanceof MessageSizeExceededError ? 1009 : 1007
27420+
failWebsocketConnectionWithCode(this.ws, code, error.message)
2734427421
return
2734527422
}
2734627423

27347-
this.writeFragments(data)
27424+
if (!this.writeFragments(data)) {
27425+
return
27426+
}
2734827427

2734927428
if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
27350-
failWebsocketConnection(this.ws, new MessageSizeExceededError().message)
27429+
failWebsocketConnectionWithCode(this.ws, 1009, new MessageSizeExceededError().message)
2735127430
return
2735227431
}
2735327432

@@ -27417,8 +27496,17 @@ class ByteParser extends Writable {
2741727496
}
2741827497

2741927498
writeFragments (fragment) {
27499+
if (
27500+
this.#maxFragments > 0 &&
27501+
this.#fragments.length === this.#maxFragments
27502+
) {
27503+
failWebsocketConnectionWithCode(this.ws, 1008, 'Too many message fragments')
27504+
return false
27505+
}
27506+
2742027507
this.#fragmentsBytes += fragment.length
2742127508
this.#fragments.push(fragment)
27509+
return true
2742227510
}
2742327511

2742427512
consumeFragments () {
@@ -28467,9 +28555,12 @@ class WebSocket extends EventTarget {
2846728555
// once this happens, the connection is open
2846828556
this[kResponse] = response
2846928557

28470-
const maxPayloadSize = this[kController]?.dispatcher?.webSocketOptions?.maxPayloadSize
28558+
const webSocketOptions = this[kController]?.dispatcher?.webSocketOptions
28559+
const maxFragments = webSocketOptions?.maxFragments
28560+
const maxPayloadSize = webSocketOptions?.maxPayloadSize
2847128561

2847228562
const parser = new ByteParser(this, parsedExtensions, {
28563+
maxFragments,
2847328564
maxPayloadSize
2847428565
})
2847528566
parser.on('drain', onParserDrain)

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ tunnel@^0.0.6:
211211
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
212212

213213
undici@^6.23.0:
214-
version "6.26.0"
215-
resolved "https://registry.yarnpkg.com/undici/-/undici-6.26.0.tgz#333a35b7f519c48d2dc6aeb38e4e91d9274e0652"
216-
integrity sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==
214+
version "6.27.0"
215+
resolved "https://registry.yarnpkg.com/undici/-/undici-6.27.0.tgz#41f9e48f7c5a40d27376caaead8c9a9fc7bca9c4"
216+
integrity sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==
217217

218218
universal-user-agent@^7.0.0, universal-user-agent@^7.0.2:
219219
version "7.0.3"

0 commit comments

Comments
 (0)