19 Commits

Author SHA1 Message Date
Damien Arrachequesne
9b6f9711da chore(release): 3.0.2
Diff: https://github.com/socketio/socket.io/compare/3.0.1...3.0.2
2020-11-18 00:53:51 +01:00
Damien Arrachequesne
43705d7a91 fix: merge Engine.IO options
So that the following example:

```js
const io = require('socket.io')({
  pingTimeout: 10000
});

io.listen(3000);
```

behaves the same as:

```js
const io = require('socket.io')(3000, {
  pingTimeout: 10000
});
```

Before this change, the options in the first example were not forwarded
to the Engine.IO constructor, which is not really intuitive.

The previous syntax (which is still valid):

```js
const io = require('socket.io')();

io.listen(3000, {
  pingTimeout: 10000
});
```
2020-11-17 23:33:18 +01:00
Damien Arrachequesne
54bf4a44e9 feat: emit an Error object upon middleware error
This commit restores the ability to send additional data in the
middleware functions, which was removed during the rewrite to
Typescript ([1]).

The only difference with the previous implementation is that the client
will now emit a "connect_error" (previously, "error") event with an
actual Error object, with both the message and an optional "data"
attribute.

```js
// server-side
io.use((socket, next) => {
  const err = new Error("not authorized");
  err.data = { content: "Please retry later" };
  next(err);
});

// client-side
socket.on("connect_error", err => {
  console.log(err.message); // not authorized
  console.log(err.data.content); // Please retry later
});
```

[1]: a5581a9789
2020-10-30 22:52:08 +01:00
Damien Arrachequesne
aa7574f884 feat: serve msgpack bundle
See 71d60480af
2020-10-27 23:17:12 +01:00
Damien Arrachequesne
cacad7029a chore(release): 3.0.0-rc3
Diff: https://github.com/socketio/socket.io/compare/3.0.0-rc2...3.0.0-rc3
2020-10-27 00:44:30 +01:00
Damien Arrachequesne
d16c035d25 refactor: rename ERROR to CONNECT_ERROR
The meaning is not modified: this packet type is still used by the
server when the connection to a namespace is refused.
2020-10-26 00:29:11 +01:00
Damien Arrachequesne
5c73733985 feat: add support for catch-all listeners
Inspired from EventEmitter2 [1]

```js
io.on("connect", socket => {

  socket.onAny((event, ...args) => {});

  socket.prependAny((event, ...args) => {});

  socket.offAny(); // remove all listeners

  socket.offAny(listener);

  const listeners = socket.listenersAny();
});
```

Breaking change: the socket.use() method is removed

This method was introduced in [2] for the same feature (having a
catch-all listener), but there were two issues:

- the API is not very user-friendly, since the user has to know the structure of the packet argument
- it uses an ERROR packet, which is reserved for Namespace authentication issues (see [3])

[1]: https://github.com/EventEmitter2/EventEmitter2
[2]: https://github.com/socketio/socket.io/issues/434
[3]: https://github.com/socketio/socket.io-protocol
2020-10-25 23:44:01 +01:00
Damien Arrachequesne
129c6417bd feat: make Socket#join() and Socket#leave() synchronous
Depending on the adapter, Socket#join() may return:

- nothing (in-memory and Redis adapters)
- a promise (custom adapters)

Breaking change: Socket#join() and Socket#leave() do not accept a
callback argument anymore.

Before:

```js
socket.join("room1", () => {
 io.to("room1").emit("hello");
});
```

After:

```
socket.join("room1");
io.to("room1").emit("hello");
// or await socket.join("room1"); for custom adapters
```

Note: the need for an asynchronous method came from the Redis adapter,
which did override the Adapter#add() method in earlier versions, but
this is not the case anymore.

Reference:

- https://github.com/socketio/socket.io/blob/2.3.0/lib/socket.js#L236-L258
- https://github.com/socketio/socket.io-adapter/blob/1.1.2/index.js#L56-L65
- 05f926e13e

Related: https://github.com/socketio/socket.io/issues/3662
2020-10-22 01:50:13 +02:00
Damien Arrachequesne
0d74f290cd refactor(typings): export Socket class
In order to be able to cast it on the argument of the "connect" event:

```js
import { Socket } from "socket.io";

io.on("connect", (socket: Socket) => {
  // ...
});
```
2020-10-17 03:36:15 +02:00
Damien Arrachequesne
7603da71a5 feat: remove prod dependency to socket.io-client
The client bundles are included in the repository in order to remove
socket.io-client from the list of production dependencies and thus to
reduce the total number of dependencies when installing the server.

This means the release of the client and the server must now be in sync
(which is almost always the case actually).

The minified build is now served:

- /<path>/socket.io.js
- /<path>/socket.io.js.map
- /<path>/socket.io.min.js
- /<path>/socket.io.min.js.map

The content will now be compressed as well.
2020-10-17 02:11:15 +02:00
Damien Arrachequesne
91cd255ba7 fix: close clients with no namespace
After a given timeout, a client that did not join any namespace will be
closed in order to prevent malicious clients from using the server
resources.

The timeout defaults to 45 seconds, in order not to interfere with the
Engine.IO heartbeat mechanism (30 seconds).
2020-10-15 11:54:06 +02:00
Damien Arrachequesne
58b66f8089 refactor: hide internal methods and properties
There is no concept of package-private methods in TypeScript, so we'll
just prefix them with "_" and mark them as private in the JSDoc.
2020-10-15 11:54:06 +02:00
Damien Arrachequesne
c0d171f728 test: use the reconnect event of the Manager
Following 132f8ec918
2020-10-13 23:02:09 +02:00
Damien Arrachequesne
9c7a48d866 test: use the complete export name
Following fa7d41f55d

Ref: https://nodejs.org/dist/latest-v14.x/docs/api/packages.html#packages_subpath_exports
2020-10-13 23:02:09 +02:00
Damien Arrachequesne
4bd5b2339a feat: throw upon reserved event names
These events cannot be used by the end users, because they are part of
the Socket.IO public API, so using them will now throw an error
explicitly.
2020-10-13 23:02:09 +02:00
Damien Arrachequesne
a8c0600609 feat: remove the 'origins' option
The underlying Engine.IO server now supports a 'cors' option, which
will be forwarded to the cors module.

Breaking change: the 'origins' option is removed

Before:

```js
new Server(3000, {
  origins: ["https://example.com"]
});
```

The 'origins' option was used in the allowRequest method, in order to
determine whether the request should pass or not. And the Engine.IO
server would implicitly add the necessary Access-Control-Allow-xxx
headers.

After:

```js
new Server(3000, {
  cors: {
    origin: "https://example.com",
    methods: ["GET", "POST"],
    allowedHeaders: ["content-type"]
  }
});
```

The already existing 'allowRequest' option can be used for validation:

```js
new Server(3000, {
  allowRequest: (req, callback) => {
    callback(null, req.headers.referer.startsWith("https://example.com"));
  }
});
```
2020-10-13 23:02:08 +02:00
Damien Arrachequesne
83a2356648 refactor: properly delegate to the main namespace 2020-10-13 23:02:08 +02:00
Damien Arrachequesne
3289f7ec37 feat: remove the implicit connection to the default namespace
In previous versions, a client was always connected to the default
namespace, even if it requested access to another namespace.

This meant that the middlewares registered for the default namespace
were triggered in any case, which is a surprising behavior for end
users.

This also meant that the query option of the Socket on the client-side
was not sent in the Socket.IO CONNECT packet for the default namespace:

```js
// default namespace: query sent in the query params
const socket = io({
  query: {
    abc: "def"
  }
});

// another namespace: query sent in the query params + the CONNECT packet
const socket = io("/admin", {
  query: {
    abc: "def"
  }
});
```

The client will now send a CONNECT packet in any case, and the query
option of the Socket is renamed to "auth", in order to make a clear
distinction with the query option of the Manager (included in the query
parameters of the HTTP requests).

```js
// server-side
io.use((socket, next) => {
  // not triggered anymore
});

io.of("/admin").use((socket, next => {
  // triggered
  console.log(socket.handshake.query.abc); // "def"
  console.log(socket.handshake.auth.abc); // "123"
});

// client-side
const socket = io("/admin", {
  query: {
    abc: "def"
  },
  auth: {
    abc: "123"
  }
});
```
2020-10-13 23:02:07 +02:00
Damien Arrachequesne
7a51c76413 refactor: migrate tests to TypeScript 2020-10-13 23:02:06 +02:00