undici 6.24.0 → 6.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -20,7 +20,6 @@ When passing an object as the second argument, the following options are availab
|
|
|
20
20
|
* **protocols** `string | string[]` (optional) - Subprotocol(s) to request the server use.
|
|
21
21
|
* **dispatcher** `Dispatcher` (optional) - A custom [`Dispatcher`](/docs/docs/api/Dispatcher.md) to use for the connection.
|
|
22
22
|
* **headers** `HeadersInit` (optional) - Custom headers to include in the WebSocket handshake request.
|
|
23
|
-
* **maxDecompressedMessageSize** `number` (optional) - Maximum allowed size in bytes for decompressed messages when using the `permessage-deflate` extension. **Default:** `4194304` (4 MB).
|
|
24
23
|
|
|
25
24
|
### Example:
|
|
26
25
|
|
|
@@ -45,20 +44,6 @@ import { WebSocket } from 'undici'
|
|
|
45
44
|
const ws = new WebSocket('wss://echo.websocket.events', ['echo', 'chat'])
|
|
46
45
|
```
|
|
47
46
|
|
|
48
|
-
### Example with custom decompression limit:
|
|
49
|
-
|
|
50
|
-
To protect against decompression bombs (small compressed payloads that expand to very large sizes), you can set a custom limit:
|
|
51
|
-
|
|
52
|
-
```mjs
|
|
53
|
-
import { WebSocket } from 'undici'
|
|
54
|
-
|
|
55
|
-
const ws = new WebSocket('wss://echo.websocket.events', {
|
|
56
|
-
maxDecompressedMessageSize: 1 * 1024 * 1024
|
|
57
|
-
})
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
> ⚠️ **Security Note**: The `maxDecompressedMessageSize` option protects against memory exhaustion attacks where a malicious server sends a small compressed payload that decompresses to an extremely large size. If you increase this limit significantly above the default, ensure your application can handle the increased memory usage.
|
|
61
|
-
|
|
62
47
|
## Read More
|
|
63
48
|
|
|
64
49
|
- [MDN - WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
|
@@ -17,9 +17,6 @@ class PerMessageDeflate {
|
|
|
17
17
|
|
|
18
18
|
#options = {}
|
|
19
19
|
|
|
20
|
-
/** @type {number} */
|
|
21
|
-
#maxDecompressedSize
|
|
22
|
-
|
|
23
20
|
/** @type {boolean} */
|
|
24
21
|
#aborted = false
|
|
25
22
|
|
|
@@ -28,12 +25,10 @@ class PerMessageDeflate {
|
|
|
28
25
|
|
|
29
26
|
/**
|
|
30
27
|
* @param {Map<string, string>} extensions
|
|
31
|
-
* @param {{ maxDecompressedMessageSize?: number }} [options]
|
|
32
28
|
*/
|
|
33
|
-
constructor (extensions
|
|
29
|
+
constructor (extensions) {
|
|
34
30
|
this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover')
|
|
35
31
|
this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits')
|
|
36
|
-
this.#maxDecompressedSize = options.maxDecompressedMessageSize ?? kDefaultMaxDecompressedSize
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
decompress (chunk, fin, callback) {
|
|
@@ -75,7 +70,7 @@ class PerMessageDeflate {
|
|
|
75
70
|
|
|
76
71
|
this.#inflate[kLength] += data.length
|
|
77
72
|
|
|
78
|
-
if (this.#inflate[kLength] >
|
|
73
|
+
if (this.#inflate[kLength] > kDefaultMaxDecompressedSize) {
|
|
79
74
|
this.#aborted = true
|
|
80
75
|
this.#inflate.removeAllListeners()
|
|
81
76
|
this.#inflate.destroy()
|
|
@@ -37,23 +37,18 @@ class ByteParser extends Writable {
|
|
|
37
37
|
/** @type {Map<string, PerMessageDeflate>} */
|
|
38
38
|
#extensions
|
|
39
39
|
|
|
40
|
-
/** @type {{ maxDecompressedMessageSize?: number }} */
|
|
41
|
-
#options
|
|
42
|
-
|
|
43
40
|
/**
|
|
44
41
|
* @param {import('./websocket').WebSocket} ws
|
|
45
42
|
* @param {Map<string, string>|null} extensions
|
|
46
|
-
* @param {{ maxDecompressedMessageSize?: number }} [options]
|
|
47
43
|
*/
|
|
48
|
-
constructor (ws, extensions
|
|
44
|
+
constructor (ws, extensions) {
|
|
49
45
|
super()
|
|
50
46
|
|
|
51
47
|
this.ws = ws
|
|
52
48
|
this.#extensions = extensions == null ? new Map() : extensions
|
|
53
|
-
this.#options = options
|
|
54
49
|
|
|
55
50
|
if (this.#extensions.has('permessage-deflate')) {
|
|
56
|
-
this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions
|
|
51
|
+
this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions))
|
|
57
52
|
}
|
|
58
53
|
}
|
|
59
54
|
|
|
@@ -44,9 +44,6 @@ class WebSocket extends EventTarget {
|
|
|
44
44
|
/** @type {SendQueue} */
|
|
45
45
|
#sendQueue
|
|
46
46
|
|
|
47
|
-
/** @type {{ maxDecompressedMessageSize?: number }} */
|
|
48
|
-
#options
|
|
49
|
-
|
|
50
47
|
/**
|
|
51
48
|
* @param {string} url
|
|
52
49
|
* @param {string|string[]} protocols
|
|
@@ -120,11 +117,6 @@ class WebSocket extends EventTarget {
|
|
|
120
117
|
// 10. Set this's url to urlRecord.
|
|
121
118
|
this[kWebSocketURL] = new URL(urlRecord.href)
|
|
122
119
|
|
|
123
|
-
// Store options for later use (e.g., maxDecompressedMessageSize)
|
|
124
|
-
this.#options = {
|
|
125
|
-
maxDecompressedMessageSize: options.maxDecompressedMessageSize
|
|
126
|
-
}
|
|
127
|
-
|
|
128
120
|
// 11. Let client be this's relevant settings object.
|
|
129
121
|
const client = environmentSettingsObject.settingsObject
|
|
130
122
|
|
|
@@ -443,7 +435,7 @@ class WebSocket extends EventTarget {
|
|
|
443
435
|
// once this happens, the connection is open
|
|
444
436
|
this[kResponse] = response
|
|
445
437
|
|
|
446
|
-
const parser = new ByteParser(this, parsedExtensions
|
|
438
|
+
const parser = new ByteParser(this, parsedExtensions)
|
|
447
439
|
parser.on('drain', onParserDrain)
|
|
448
440
|
parser.on('error', onParserError.bind(this))
|
|
449
441
|
|
|
@@ -546,19 +538,6 @@ webidl.converters.WebSocketInit = webidl.dictionaryConverter([
|
|
|
546
538
|
{
|
|
547
539
|
key: 'headers',
|
|
548
540
|
converter: webidl.nullableConverter(webidl.converters.HeadersInit)
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
key: 'maxDecompressedMessageSize',
|
|
552
|
-
converter: webidl.nullableConverter((V) => {
|
|
553
|
-
V = webidl.converters['unsigned long long'](V)
|
|
554
|
-
if (V <= 0) {
|
|
555
|
-
throw webidl.errors.exception({
|
|
556
|
-
header: 'WebSocket constructor',
|
|
557
|
-
message: 'maxDecompressedMessageSize must be greater than 0'
|
|
558
|
-
})
|
|
559
|
-
}
|
|
560
|
-
return V
|
|
561
|
-
})
|
|
562
541
|
}
|
|
563
542
|
])
|
|
564
543
|
|
package/package.json
CHANGED
package/types/websocket.d.ts
CHANGED
|
@@ -146,12 +146,5 @@ export declare const ErrorEvent: {
|
|
|
146
146
|
interface WebSocketInit {
|
|
147
147
|
protocols?: string | string[],
|
|
148
148
|
dispatcher?: Dispatcher,
|
|
149
|
-
headers?: HeadersInit
|
|
150
|
-
/**
|
|
151
|
-
* Maximum size in bytes for decompressed WebSocket messages.
|
|
152
|
-
* When a message exceeds this limit during decompression, the connection
|
|
153
|
-
* will be closed with status code 1009 (Message Too Big).
|
|
154
|
-
* @default 4194304 (4 MB)
|
|
155
|
-
*/
|
|
156
|
-
maxDecompressedMessageSize?: number
|
|
149
|
+
headers?: HeadersInit
|
|
157
150
|
}
|