A "new_namespace" event will be emitted when a new namespace is created:
```js
io.on("new_namespace", (namespace) => {
// ...
});
```
This could be used for example for registering the same middleware for
each namespace.
See https://github.com/socketio/socket.io/issues/3851
Syntax:
```js
// server A
io.serverSideEmit("hello", "world");
// server B
io.on("hello", (arg) => {
console.log(arg); // prints "world"
});
```
With acknowledgements:
```js
// server A
io.serverSideEmit("hello", "world", (err, responses) => {
console.log(responses); // prints ["hi"]
});
// server B
io.on("hello", (arg, callback) => {
callback("hi");
});
```
This feature replaces the customHook/customRequest API from the Redis
adapter: https://github.com/socketio/socket.io-redis/issues/370
Packets that are sent to multiple clients will now be pre-encoded for
the WebSocket transport (which means simply prepending "4" - which is
the "message" packet type in Engine.IO).
Note: buffers are not pre-encoded, since they are sent without
modification over the WebSocket connection
See also: 7706b123df
engine.io diff: https://github.com/socketio/engine.io/compare/5.0.0...5.1.0
A few notes:
- only the first element is pre-encoded, because the other elements are
buffers and will be sent as is over the WebSocket connection
- using `socket.packet()` was unexpectedly working, we will now use
`socket.client.writeToEngine()` (see [1])
See also: 7706b123df
[1]: https://github.com/socketio/socket.io/issues/3775
Before this change, `require("socket.io").Socket` would return
"undefined".
Note: having access to the Socket class allows users to modify its
prototype.
Related: https://github.com/socketio/socket.io/issues/3726
Before this change, `require("socket.io-client").Socket` would return
"undefined".
Note: having access to the Socket class allows users to modify its
prototype.
Related: https://github.com/socketio/socket.io/issues/3726
Before this commit, an event sent in the "connect" handler could be
sent before the events that were buffered while disconnected.
```js
socket.on("connect", () => {
socket.emit("bar");
});
socket.emit("foo"); // buffered while disconnected
```
In the example above, the "bar" event was sent first, which is not
correct.
Related: https://github.com/socketio/socket.io-client/issues/1458
When passing the same `options` argument for two distinct Socket
instances, a new Manager was created:
```js
const opts = {};
const socket1 = io("/foo", opts);
const socket2 = io("/bar", opts);
console.log(socket1.io === socket2.io); // false
```
This bug was introduced by [1].
Note: the `options` argument is modified at the `socket.io-client`
level (path, query) and at the `engine.io-client` level (host, port),
which may not be optimal.
[1]: 7a0c2b504f
Related: https://github.com/socketio/socket.io/issues/3898
Since [1], the socket is now closed when receiving the "beforeunload"
event in the browser.
This change was meant to fix a discrepancy between Chrome and Firefox
when the user reloads/closes a browser tab: Firefox would close the
connection (and emit a "disconnect" event, at the Socket.IO level), but
not Chrome (see [2]).
But it also closes the connection when there is another "beforeunload"
handler, for example when the user is prompted "are you sure you want
to leave this page?".
Note: calling "stopImmediatePropagation()" was a possible workaround:
```js
window.addEventListener('beforeunload', (event) => {
event.preventDefault();
event.stopImmediatePropagation();
event.returnValue = 'are you sure you want to leave this page?';
});
```
This commit adds a "closeOnBeforeunload" option, which controls whether
a handler is registered for the "beforeunload" event.
Syntax:
```js
const socket = require('engine.io-client')('ws://localhost', {
closeOnBeforeunload: false // defaults to true
});
```
[1]: ed48b5dc34
[2]: https://github.com/socketio/socket.io/issues/3639
Related:
- https://github.com/socketio/engine.io-client/issues/661
- https://github.com/socketio/engine.io-client/issues/658
- https://github.com/socketio/socket.io-client/issues/1451
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
This option will be used when broadcasting a packet to multiple clients,
in order to only encode the packet once.
Usage:
```js
socket.write("test", {
wsPreEncoded: "4test"
});
```
Note: pre-encoding the content with HTTP long-polling is a bit harder,
since the concatenation of the packets is specific to each client.
This change should reduce memory usage when many packets are emitted to
many clients in a burst.
Co-authored-by: Branislav Katreniak <bkatreniak@slido.com>
Those events will be emitted before the response headers are written to
the socket:
- "initial_headers": on the first request of the connection
- "headers": on all requests (HTTP long-polling and WebSocket upgrade)
Syntax:
```js
server.on("initial_headers", (headers, req) => {
headers["test"] = "123";
headers["set-cookie"] = "mycookie=456";
});
server.on("headers", (headers, req) => {
headers["test"] = "789";
});
```
Related:
- https://github.com/socketio/engine.io/issues/557
- https://github.com/socketio/socket.io/issues/3630
The "connection_error" event will be emitted when one of the following
errors occurs:
- Transport unknown
- Session ID unknown
- Bad handshake method
- Bad request
- Forbidden
- Unsupported protocol version
Syntax:
```js
server.on("connection_error", (err) => {
console.log(err.req); // the request object
console.log(err.code); // the error code, for example 1
console.log(err.message); // the error message, for example "Session ID unknown"
console.log(err.context); // some additional error context
});
```
Related:
- https://github.com/socketio/socket.io/issues/3819
- https://github.com/socketio/engine.io/issues/576
In some cases, a "Transport not open" error could be thrown when the
transport was silently closed in the onbeforeunload event (added in
[1]).
To reproduce:
```js
window.addEventListener("unload", () => {
socket.write("...");
});
```
[1]: ed48b5dc34
Related: https://github.com/socketio/socket.io/issues/3838