The "drain" event (added in [1]) had two different meanings:
- the transport is ready to be written
- the packets are sent over the wire
For the WebSocket and the WebTransport transports, those two events
happen at the same time, but this is not the case for the HTTP
long-polling transport:
- the transport is ready to be written when the client sends a GET request
- the packets are sent over the wire when the server responds to the GET request
Which caused an issue with send callbacks during an upgrade, since the
packets were written but the client would not open a new GET request.
There are now two distinct events: "ready" and "drain"
Related: https://github.com/socketio/engine.io/issues/695
[1]: 2a93f06e27
With the `websocket` transport, the callbacks which indicate that the
packets are actually written were not properly called.
Example:
```js
socket.send("hello", () => {
// the message has been written to the underlying transport
});
```
The bug was caused by the `websocket` transport (and `webtransport` as
well) having its `supportsFraming` property set to `true`, despite
having been changed in [1] to emit a single `drain` event for each
batch of messages written to the transport like the `polling` transport
always did. Note that although [1] is partially reverted in [2], the
new `drain` event behavior is preserved as called out in that commit's
message.
The `supportsFraming` attribute was introduced in [3] (amended by [4])
as a way to distinguish transports that emit one `drain` per message
from those that emit one `drain` per batch. Since the delivery of
`send` callbacks depends on matching `drain` events with
`transport.send` calls, that distinction is vital to correct behavior.
However, now that all transports have converged to "one `drain` per
batch" behavior, this `supportsFraming` property can be retired (and
the code for calling callbacks simplified).
[1]: https://github.com/socketio/engine.io/pull/618
[2]: a65a047526
[3]: https://github.com/socketio/engine.io/pull/130
[4]: https://github.com/socketio/engine.io/pull/132
Related: https://github.com/socketio/engine.io/issues/698
A reference to the initial IncomingMessage object (the first HTTP
request of the session) is kept in memory by default (`socket.request`),
so its attached ServerResponse object (`req.res`) would not be
garbage-collected. This will now be the case.
Note: the IncomingMessage object is needed in two cases:
- when working with the `express-session` middleware (`request.session`)
- when fetching the certificate of the client with `request.socket.getPeerCertificate()`
That's why removing it would be a breaking change.
This header should not be needed since the client already includes a
cache busting query parameter ("t"), but a misconfigured CDN could
ignore the query parameters and cache the server response.
Related: https://github.com/socketio/socket.io/issues/4842
This reverts commit [1], which was included in `engine.io@5.1.0` and
`socket.io@4.1.0`.
The WebSocket connection was closed before all packets were written
out, so for example when calling `socket.disconnect(true)` on the
Socket.IO server (which disconnect from all namespaces and close the
connection), the client would receive only the first disconnect packet
and kept trying to reconnect to the other namespaces.
The only difference with the previous implementation (pre 5.1.0) is
that the "drain" event gets only called once at the end, and not after
each packet.
[1]: ad5306aeae
Related: https://github.com/socketio/engine.io/issues/648
This major bump creates a lot of noise, but it is necessary for
prettier to be able to parse new syntax such as:
- typed imports: `import { type xxx } from ...`
- private attributes: `class A { #b; #c() {} }`
With the engine based on µWebSockets.js (introduced in version 6.1.0),
a huge request body split in multiple chunks would throw the following
error:
> node:buffer:254
> TypedArrayPrototypeSet(target, source, targetStart);
> ^
>
> TypeError: Cannot perform %TypedArray%.prototype.set on a detached ArrayBuffer
> at Buffer.set (<anonymous>)
> at _copyActual (node:buffer:254:3)
> node:buffer:254
> TypedArrayPrototypeSet(target, source, targetStart);
> ^
>
> TypeError: Cannot perform %TypedArray%.prototype.set on a detached ArrayBuffer
> at Buffer.set (<anonymous>)
> at _copyActual (node:buffer:254:3)
> at Function.concat (node:buffer:562:12)
> at onEnd (.../node_modules/engine.io/build/transports-uws/polling.js:126:32)
> at .../node_modules/engine.io/build/transports-uws/polling.js:143:17
Note: µWebSockets.js does not currently support chunked transfer
encoding.