When a packet contains binary elements, the built-in parser does not modify them and simply sends them in their own WebSocket frame.
Example: `socket.emit("some event", Buffer.of(1,2,3))`
is encoded and transferred as:
- 1st frame: 51-["some event",{"_placeholder":true,"num":0}]
- 2nd frame: <buffer 01 02 03>
where:
- `5` is the type of the packet (binary message)
- `1` is the number of binary attachments
- `-` is the separator
- `["some event",{"_placeholder":true,"num":0}]` is the payload (including the placeholder)
On the receiving end, the parser reads the number of attachments and buffers them until they are all received.
Before this change, the built-in parser accepted any number of binary attachments, which could be exploited to make the server run out of memory.
The number of attachments is now limited to 10, which should be sufficient for most use cases.
The limit can be increased with a custom `parser`:
```js
import { Encoder, Decoder } from "socket.io-parser";
const io = new Server({
parser: {
Encoder,
Decoder: class extends Decoder {
constructor() {
super({
maxAttachments: 20
});
}
}
}
});
```
Since engine.io@6.6.5, the generated .d.ts files import types from "ws"
(WebSocket, PerMessageDeflateOptions), but @types/ws was not declared as
a dependency. This causes TypeScript compilation errors for consumers
who do not have @types/ws installed.
This follows the existing pattern where @types/cors and @types/node are
already listed as dependencies.
Related: https://github.com/socketio/socket.io/issues/5437
The uServer (uWebSockets.js) implementation did not emit
"initial_headers" and "headers" events during WebSocket upgrades,
unlike the regular Server which does this via the ws "headers" event.
Related: https://github.com/socketio/socket.io/issues/5300
When using `emitWithAck` with a timeout, if clients didn't respond
and the timeout triggers, the ack callbacks remained in `socket.acks`
Map indefinitely, causing a memory leak.
Related: https://github.com/socketio/socket.io/issues/4984
We should eventually be able to replace:
- mocha and nyc with Node.js built-in test runner (`node:test`)
- expect.js with Node.js built-in assertion library (`node:assert`)
The "_placeholder" attribute is used when sending binary data, and was
incorrectly mangled (converted to a random short property, like "it",
to reduce the bundle size).
Related:
- ca9e994815
- https://github.com/socketio/socket.io/issues/5215
[skip ci]
The init() method of the adapter will now be called when creating a namespace with `io.of(<the-namespace>)`.
Note: any promise rejection is silently caught, as I don't see how we could properly expose the promise.
```js
const io = new Server({
adapter: myAdapter
});
// under the hood, this:
// - implicitly creates the main namespace (/)
// - creates an instance of `myAdapter` for the main namespace
// - calls `myAdapter.init()` (with this change)
```
Related:
- https://github.com/socketio/socket.io/issues/3662
- https://github.com/socketio/socket.io-postgres-adapter/issues/16