<commit_before>title: Socket.IO 4.1.0
permalink: /blog/socket-io-4-1-0/
date: 2021-05-14
author_name: <NAME>
author_link: https://github.com/darrachequesne
alias: blog/index.html
---

Hello everyone!

We have just published a new minor version of Socket.IO: [4.1.0](https://github.com/socketio/socket.io/releases/tag/4.1.0)

## New features

- [Add support for inter-server communication](#Add-support-for-inter-server-communication)
- [Emit an event when a namespace is created](#Emit-an-event-when-a-namespace-is-created)
- [Add a way to customize the response headers](#Add-a-way-to-customize-the-response-headers)
- [Add a way to get access to the reason of a connection error](#Add-a-way-to-get-access-to-the-reason-of-a-connection-error)
- [Add a way to ignore the `beforeunload` event](#Add-a-way-to-ignore-the-beforeunload-event)

### Add support for inter-server communication

This feature might be useful in a multi-server setup: you can now broadcast events between your Socket.IO servers.

Syntax:

```js
io.serverSideEmit("hello", "world");
```

And on the receiving side:

```js
io.on("hello", (arg1) => {
  console.log(arg1); // prints "world"
});
```

Acknowledgements are supported too:

```js
// server A
io.serverSideEmit("ping", (err, responses) => {
  console.log(responses[0]); // prints "pong"
});

// server B
io.on("ping", (cb) => {
  cb("pong");
});
```

A few notes:

- the events are specific to each [namespace](/docs/v4/namespaces/)

```js
// server A
io.of("/custom").serverSideEmit("sync");

// server B
io.of("/custom").on("sync", () => {
  // ...
});
```

- the `connection`, `connect` and `new_namespace` (see [below](#Emit-an-event-when-a-namespace-is-created)) strings are reserved and cannot be used in your application.

- you can send any number of arguments, but binary structures are currently not supported (the array of arguments will be `JSON.stringify`-ed)

Example:

```js
io.serverSideEmit("hello", "world", 1, "2", { 3: "4" });
```

The [Redis adapter](https://github.com/socketio/socket.io-redis-adapter) and its [associated emitter](https://github.com/socketio/socket.io-redis-emitter) have been updated to support this new functionality.

### Emit an event when a namespace is created

The `new_namespace` event will be emitted by the Server instance when a new namespace is created:

```js
io.on("new_namespace", (namespace) => {
  // ...
});
```

This can be useful for example:

- to attach a shared middleware to each namespace

```js
io.on("new_namespace", (namespace) => {
  namespace.use(myMiddleware);
});
```

- to track the [dynamically created](/docs/v4/namespaces/#Dynamic-namespaces) namespaces

```js
io.of(/\/nsp-\w+/);

io.on("new_namespace", (namespace) => {
  console.log(namespace.name);
});
```

### Add a way to customize the response headers

The underlying Engine.IO server, which manages the low-level connection (HTTP long-polling and/or WebSocket), will now emit two additional events:

- `initial_headers`
- `headers`

Like the name suggests, the `initial_headers` event will be emitted only for the first HTTP request of the session, while the `headers` event will be emitted for each HTTP request (including the WebSocket upgrade).

Example:

```js
io.engine.on("initial_headers", (headers, req) => {
  headers["test"] = "123";
  headers["set-cookie"] = "mycookie=456";
});

io.engine.on("headers", (headers, req) => {
  headers["test"] = "789";
});
```

Note: it was previously possible to achieve this by listening to the "request" event, but this should be easier with those new events:

```js
const httpServer = require("http").createServer();
const { Server } = require("socket.io");
const io = new Server(httpServer);

httpServer.prependListener("request", (req, res) => {
  res.setHeader("test", "789");
});
```

### Add a way to get access to the reason of a connection error

The underlying Engine.IO server will also emit a new event: `connection_error`.

Syntax:

```js
io.engine.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
});
```

Here is the list of possible error codes:

| Code | Message |
|:----:|:-------:|
| 0 | "Transport unknown"
| 1 | "Session ID unknown"
| 2 | "Bad handshake method"
| 3 | "Bad request"
| 4 | "Forbidden"
| 5 | "Unsupported protocol version"

### Add a way to ignore the `beforeunload` event

A few months ago, a user [reported](https://github.com/socketio/socket.io/issues/3639) a weird behavior when reloading a page: on Firefox, the Socket instance would emit a `disconnect` event, but not on Chrome or Safari.

We have published a fix for this issue in `socket.io-client@3.1.1`, by silently closing the connection when receiving a [`beforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event) event from the browser.

Unfortunately, this fix had unintended consequences: if you relied on the `beforeunload` event to prompt the user for confirmation ("your last modifications are not saved yet, do you really want to leave?"), the Socket.IO connection would now be closed, even if the user decided to stay on the page.

That's why we have added the `closeOnBeforeUnload` option, to give you total control over this behavior:

```js
const socket = io("/", {
  closeOnBeforeUnload: false // defaults to true
})
```

- `closeOnBeforeUnload: true` (the default value) will make all browsers behave the same (no `disconnect` event when reloading the page)
- `closeOnBeforeUnload: false` will ignore the `beforeunload` event, but you will get a `disconnect` event on Firefox

That's all for this release, thanks for reading!
<commit_msg>docs: fix typo<commit_after>title: Socket.IO 4.1.0
permalink: /blog/socket-io-4-1-0/
date: 2021-05-14
author_name: <NAME>
author_link: https://github.com/darrachequesne
alias: blog/index.html
---

Hello everyone!

We have just published a new minor version of Socket.IO: [4.1.0](https://github.com/socketio/socket.io/releases/tag/4.1.0)

## New features

- [Add support for inter-server communication](#Add-support-for-inter-server-communication)
- [Emit an event when a namespace is created](#Emit-an-event-when-a-namespace-is-created)
- [Add a way to customize the response headers](#Add-a-way-to-customize-the-response-headers)
- [Add a way to get access to the reason of a connection error](#Add-a-way-to-get-access-to-the-reason-of-a-connection-error)
- [Add a way to ignore the `beforeunload` event](#Add-a-way-to-ignore-the-beforeunload-event)

### Add support for inter-server communication

This feature might be useful in a multi-server setup: you can now broadcast events between your Socket.IO servers.

Syntax:

```js
io.serverSideEmit("hello", "world");
```

And on the receiving side:

```js
io.on("hello", (arg1) => {
  console.log(arg1); // prints "world"
});
```

Acknowledgements are supported too:

```js
// server A
io.serverSideEmit("ping", (err, responses) => {
  console.log(responses[0]); // prints "pong"
});

// server B
io.on("ping", (cb) => {
  cb("pong");
});
```

A few notes:

- the events are specific to each [namespace](/docs/v4/namespaces/)

```js
// server A
io.of("/custom").serverSideEmit("sync");

// server B
io.of("/custom").on("sync", () => {
  // ...
});
```

- the `connection`, `connect` and `new_namespace` (see [below](#Emit-an-event-when-a-namespace-is-created)) strings are reserved and cannot be used in your application.

- you can send any number of arguments, but binary structures are currently not supported (the array of arguments will be `JSON.stringify`-ed)

Example:

```js
io.serverSideEmit("hello", "world", 1, "2", { 3: "4" });
```

The [Redis adapter](https://github.com/socketio/socket.io-redis-adapter) and its [associated emitter](https://github.com/socketio/socket.io-redis-emitter) have been updated to support this new functionality.

### Emit an event when a namespace is created

The `new_namespace` event will be emitted by the Server instance when a new namespace is created:

```js
io.on("new_namespace", (namespace) => {
  // ...
});
```

This can be useful for example:

- to attach a shared middleware to each namespace

```js
io.on("new_namespace", (namespace) => {
  namespace.use(myMiddleware);
});
```

- to track the [dynamically created](/docs/v4/namespaces/#Dynamic-namespaces) namespaces

```js
io.of(/\/nsp-\w+/);

io.on("new_namespace", (namespace) => {
  console.log(namespace.name);
});
```

### Add a way to customize the response headers

The underlying Engine.IO server, which manages the low-level connection (HTTP long-polling and/or WebSocket), will now emit two additional events:

- `initial_headers`
- `headers`

Like the name suggests, the `initial_headers` event will be emitted only for the first HTTP request of the session, while the `headers` event will be emitted for each HTTP request (including the WebSocket upgrade).

Example:

```js
io.engine.on("initial_headers", (headers, req) => {
  headers["test"] = "123";
  headers["set-cookie"] = "mycookie=456";
});

io.engine.on("headers", (headers, req) => {
  headers["test"] = "789";
});
```

Note: it was previously possible to achieve this by listening to the "request" event, but this should be easier with those new events:

```js
const httpServer = require("http").createServer();
const { Server } = require("socket.io");
const io = new Server(httpServer);

httpServer.prependListener("request", (req, res) => {
  res.setHeader("test", "789");
});
```

### Add a way to get access to the reason of a connection error

The underlying Engine.IO server will also emit a new event: `connection_error`.

Syntax:

```js
io.engine.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
});
```

Here is the list of possible error codes:

| Code | Message |
|:----:|:-------:|
| 0 | "Transport unknown"
| 1 | "Session ID unknown"
| 2 | "Bad handshake method"
| 3 | "Bad request"
| 4 | "Forbidden"
| 5 | "Unsupported protocol version"

### Add a way to ignore the `beforeunload` event

A few months ago, a user [reported](https://github.com/socketio/socket.io/issues/3639) a weird behavior when reloading a page: on Firefox, the Socket instance would emit a `disconnect` event, but not on Chrome or Safari.

We have published a fix for this issue in `socket.io-client@3.1.1`, by silently closing the connection when receiving a [`beforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event) event from the browser.

Unfortunately, this fix had unintended consequences: if you relied on the `beforeunload` event to prompt the user for confirmation ("your last modifications are not saved yet, do you really want to leave?"), the Socket.IO connection would now be closed, even if the user decided to stay on the page.

That's why we have added the `closeOnBeforeunload` option, to give you total control over this behavior:

```js
const socket = io("/", {
  closeOnBeforeunload: false // defaults to true
})
```

- `closeOnBeforeunload: true` (the default value) will make all browsers behave the same (no `disconnect` event when reloading the page)
- `closeOnBeforeunload: false` will ignore the `beforeunload` event, but you will get a `disconnect` event on Firefox

That's all for this release, thanks for reading!

{'fraction_non_alphanumeric': 0.14349353208258375, 'fraction_numerical': 0.00942345583825923, 'mean_word_length': 4.313609467455621, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 12, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5372762', 'n_tokens_mistral': 3723, 'n_tokens_neox': 3572, 'n_words': 1278}