With autoUnref set to true (default: false), the Socket.IO client will
allow the program to exit if there is no other active timer/socket in
the event system.
```js
const socket = io({
autoUnref: true
});
```
Note: this option only applies to Node.js clients.
Related: https://github.com/socketio/socket.io-client/issues/1446
Syntax:
```ts
interface ClientToServerEvents {
"my-event": (a: number, b: string, c: number[]) => void;
}
interface ServerToClientEvents {
hello: (message: string) => void;
}
const io = new Server<ClientToServerEvents, ServerToClientEvents>(httpServer);
io.emit("hello", "world");
io.on("connection", (socket) => {
socket.on("my-event", (a, b, c) => {
// ...
});
socket.emit("hello", "again");
});
```
The events are not typed by default (inferred as any), so this change
is backward compatible.
Note: we could also have reused the method here ([1]) to add types to
the EventEmitter, instead of creating a StrictEventEmitter class.
Related: https://github.com/socketio/socket.io/issues/3742
[1]: https://github.com/binier/tiny-typed-emitter
This change is necessary to get rid of:
> Critical dependency: the request of a dependency is an expression
when bundling the server with webpack.
BREAKING CHANGE: the syntax of the "wsEngine" option is updated
Before:
```js
const eioServer = require("engine.io")(httpServer, {
wsEngine: "eiows"
});
```
After:
```js
const eioServer = require("engine.io")(httpServer, {
wsEngine: require("eiows").Server
});
```
Related: https://github.com/socketio/engine.io/issues/609
socket.io-client-swift libs version <=15.2.0, which uses protocol
version 3, do not explicitly add the EIO query parameter at transport
initialization. This omission leads the server to treat the client as
a client that supports the protocol version 4, previously set as
default, which is not correct for those versions of the client lib.
From socket.io-client-swift version v16.0.0 the EIO query parameter is
explicitly passed to specify the protocol version supported, but since
the allowEIO3 parameter aims to make the server compatible with
previous versions which in most of the cases are already used in
production and not easily upgradable, it makes more sense to default
the EIO version to 3 if not explicitly set by the client since the
newer client versions pass the EIO protocol version in query
parameters.
Related: https://github.com/socketio/socket.io/issues/3794
With autoUnref set to true (default: false), the Engine.IO client will
allow the program to exit if there is no other active timer/socket in
the event system.
Note: the 'xmlhttprequest-ssl' package has been copied in the contrib/
directory, until the change is merged upstream
Related: https://github.com/socketio/engine.io-client/issues/653
This commit adds the following methods:
- fetchSockets: returns the matching socket instances
Syntax:
```js
// return all Socket instances
const sockets = await io.fetchSockets();
// return all Socket instances of the "admin" namespace in the "room1" room
const sockets = await io.of("/admin").in("room1").fetchSockets();
```
- socketsJoin: makes the matching socket instances join the specified rooms
Syntax:
```js
// make all Socket instances join the "room1" room
io.socketsJoin("room1");
// make all Socket instances of the "admin" namespace in the "room1" room join the "room2" room
io.of("/admin").in("room1").socketsJoin("room2");
```
- socketsLeave: makes the matching socket instances leave the specified rooms
Syntax:
```js
// make all Socket instances leave the "room1" room
io.socketsLeave("room1");
// make all Socket instances of the "admin" namespace in the "room1" room leave the "room2" room
io.of("/admin").in("room1").socketsLeave("room2");
```
- disconnectSockets: makes the matching socket instances disconnect
Syntax:
```js
// make all Socket instances disconnect
io.disconnectSockets();
// make all Socket instances of the "admin" namespace in the "room1" room disconnect
io.of("/admin").in("room1").disconnectSockets();
```
Those methods share the same semantics as broadcasting. They will also
work with multiple Socket.IO servers when using the Redis adapter. In
that case, the fetchSockets() method will return a list of RemoteSocket
instances, which expose a subset of the methods and attributes of the
Socket class (the "request" attribute cannot be mocked, for example).
Related:
- https://github.com/socketio/socket.io/issues/3042
- https://github.com/socketio/socket.io/issues/3418
- https://github.com/socketio/socket.io/issues/3570
- https://github.com/socketio/socket.io-redis/issues/283
This value was updated from 60000 to 5000 in [1], included in
`engine.io@3.2.0` (Feb 2018).
The reasoning back then:
Some users experienced long delays between disconnection on the
server-side and on the client-side. The "disconnect" event would take a
long time to fire in the browser, probably due to a timer being
delayed. Hence the change.
That being said, the current value (5s) now causes unexpected
disconnections when a big payload is sent over a slow network, because
it prevents the ping-pong packets from being exchanged between the
client and the server. This can also happen when a synchronous task
blocks the server for more than 5 seconds.
The new value (20s) thus seems like a good balance between quick
disconnection detection and tolerance to various delays.
Note: pingInterval + pingTimeout is still below the threshold of React
Native, which complains if a timer is set with a delay of more than 1
minute.
[1]: 65b1ad1b8a
Related:
- https://github.com/socketio/socket.io/issues/2770
- https://github.com/socketio/socket.io/issues/2769
- https://github.com/socketio/socket.io/issues/3054
- https://github.com/socketio/socket.io/issues/3376
In some cases it is necessary to pass an array of rooms instead of a single room.
New syntax:
```
io.to(["room1", "room2"]).except(["room3"]).emit(...);
socket.to(["room1", "room2"]).except(["room3"]).emit(...);
```
Related: https://github.com/socketio/socket.io/issues/3048
Previously, broadcasting to a given room (by calling `io.to()`) would
mutate the io instance, which could lead to surprising behaviors, like:
```js
io.to("room1");
io.to("room2").emit(...); // also sent to room1
// or with async/await
io.to("room3").emit("details", await fetchDetails()); // random behavior: maybe in room3, maybe to all clients
```
Calling `io.to()` (or any other broadcast modifier) will now return an
immutable instance.
Related:
- https://github.com/socketio/socket.io/issues/3431
- https://github.com/socketio/socket.io/issues/3444
This commit adds the following methods:
- fetchSockets: return the matching socket instances
- addSockets: make the matching socket instances join the specified rooms
- delSockets: make the matching socket instances leave the specified rooms
- disconnectSockets: disconnect the matching socket instances
Those methods will then be exposed by the Socket.IO server:
```js
// clear room
io.socketsLeave("room1");
// disconnect all sockets in room
io.in("room2").disconnectSockets();
// fetch socket instances in room
io.in("room3").fetchSockets();
```
This feature will also be extended in the Redis adapter to handle
multiple Socket.IO servers.
In Socket.IO v2, the Socket query option was appended to the namespace
in the CONNECT packet:
{
type: 0,
nsp: "/my-namespace?abc=123"
}
Note: the "query" option on the client-side (v2) will be found in the
"auth" attribute on the server-side:
```
// client-side
const socket = io("/nsp1", {
query: {
abc: 123
}
});
socket.query = { abc: 456 };
// server-side
const io = require("socket.io")(httpServer, {
allowEIO3: true // enable compatibility mode
});
io.of("/nsp1").on("connection", (socket) => {
console.log(socket.handshake.auth); // { abc: 456 } (the Socket query)
console.log(socket.handshake.query.abc); // 123 (the Manager query)
});
More information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/#Add-a-clear-distinction-between-the-Manager-query-option-and-the-Socket-query-option
Related: https://github.com/socketio/socket.io/issues/3791
Previously, the following code:
```js
const socket1 = io({
path: "/test1"
});
const socket2 = io({
path: "/test2"
});
```
would result in one single Manager, with the "/test2" path being
silently ignored.
Two distinct Manager instances will now be created.
Related: https://github.com/socketio/socket.io-client/issues/1225
Having type `Object` it was not possible to set values, e.g.:
```ts
if (!this.socket.io.opts.query) {
this.socket.io.opts.query = {};
}
this.socket.io.opts.query.token = 'abc123';
```
Results in error:
> Element implicitly has an 'any' type because expression of type '"token"' can't be used to index type 'Object'.
There was two issues with this behavior:
- v3 clients (with allowEIO3: true) were also receiving a "ping" after
a successful upgrade, which is incorrect (in v3, it's the client that
sends the "ping", and the server answers with a "pong")
- the ping timer is not reset after upgrade on the client-side, so an
upgrade which took longer than the `pingTimeout` duration could lead to
a "ping timeout" error on the client-side
I think the latter issue is present since the initial implementation.
Related: https://github.com/socketio/socket.io-client-swift/pull/1309#issuecomment-768475704