Skip to content

Commit 54bf4a4

Browse files
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]: a5581a9
1 parent aa7574f commit 54bf4a4

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed

lib/client.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ export class Client {
9393
this._packet({
9494
type: PacketType.CONNECT_ERROR,
9595
nsp: name,
96-
data: "Invalid namespace"
96+
data: {
97+
message: "Invalid namespace"
98+
}
9799
});
98100
}
99101
});

lib/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import path from "path";
77
import engine from "engine.io";
88
import { Client } from "./client";
99
import { EventEmitter } from "events";
10-
import { Namespace } from "./namespace";
10+
import { ExtendedError, Namespace } from "./namespace";
1111
import { ParentNamespace } from "./parent-namespace";
1212
import { Adapter, Room, SocketId } from "socket.io-adapter";
1313
import * as parser from "socket.io-parser";
@@ -593,7 +593,7 @@ export class Server extends EventEmitter {
593593
* @public
594594
*/
595595
public use(
596-
fn: (socket: Socket, next: (err?: Error) => void) => void
596+
fn: (socket: Socket, next: (err?: ExtendedError) => void) => void
597597
): Server {
598598
this.sockets.use(fn);
599599
return this;

lib/namespace.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import { Adapter, Room, SocketId } from "socket.io-adapter";
88

99
const debug = debugModule("socket.io:namespace");
1010

11+
export interface ExtendedError extends Error {
12+
data?: any;
13+
}
14+
1115
export class Namespace extends EventEmitter {
1216
public readonly name: string;
1317
public readonly sockets: Map<SocketId, Socket> = new Map();
@@ -18,7 +22,9 @@ export class Namespace extends EventEmitter {
1822
readonly server: Server;
1923

2024
/** @private */
21-
_fns: Array<(socket: Socket, next: (err: Error) => void) => void> = [];
25+
_fns: Array<
26+
(socket: Socket, next: (err: ExtendedError) => void) => void
27+
> = [];
2228

2329
/** @private */
2430
_rooms: Set<Room> = new Set();
@@ -60,7 +66,7 @@ export class Namespace extends EventEmitter {
6066
* @public
6167
*/
6268
public use(
63-
fn: (socket: Socket, next: (err?: Error) => void) => void
69+
fn: (socket: Socket, next: (err?: ExtendedError) => void) => void
6470
): Namespace {
6571
this._fns.push(fn);
6672
return this;
@@ -73,7 +79,7 @@ export class Namespace extends EventEmitter {
7379
* @param {Function} fn - last fn call in the middleware
7480
* @private
7581
*/
76-
private run(socket: Socket, fn: (err: Error) => void) {
82+
private run(socket: Socket, fn: (err: ExtendedError) => void) {
7783
const fns = this._fns.slice(0);
7884
if (!fns.length) return fn(null);
7985

@@ -129,7 +135,11 @@ export class Namespace extends EventEmitter {
129135
this.run(socket, err => {
130136
process.nextTick(() => {
131137
if ("open" == client.conn.readyState) {
132-
if (err) return socket._error(err.message);
138+
if (err)
139+
return socket._error({
140+
message: err.message,
141+
data: err.data
142+
});
133143

134144
// track socket
135145
this.sockets.set(socket.id, socket);

test/socket.io.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ describe("socket.io", () => {
522522
srv.listen(() => {
523523
const socket = client(srv, "/doesnotexist");
524524
socket.on("connect_error", err => {
525-
expect(err).to.be("Invalid namespace");
525+
expect(err.message).to.be("Invalid namespace");
526526
done();
527527
});
528528
});
@@ -814,7 +814,7 @@ describe("socket.io", () => {
814814
sio.of(/^\/dynamic-\d+$/);
815815
sio.of((name, query, next) => next(null, "/dynamic-101" === name));
816816
socket.on("connect_error", err => {
817-
expect(err).to.be("Invalid namespace");
817+
expect(err.message).to.be("Invalid namespace");
818818
done();
819819
});
820820
});
@@ -2185,7 +2185,30 @@ describe("socket.io", () => {
21852185
done(new Error("nope"));
21862186
});
21872187
socket.on("connect_error", err => {
2188-
expect(err).to.be("Authentication error");
2188+
expect(err.message).to.be("Authentication error");
2189+
done();
2190+
});
2191+
});
2192+
});
2193+
2194+
it("should pass an object", done => {
2195+
const srv = createServer();
2196+
const sio = new Server(srv);
2197+
sio.use((socket, next) => {
2198+
const err = new Error("Authentication error");
2199+
// @ts-ignore
2200+
err.data = { a: "b", c: 3 };
2201+
next(err);
2202+
});
2203+
srv.listen(() => {
2204+
const socket = client(srv);
2205+
socket.on("connect", () => {
2206+
done(new Error("nope"));
2207+
});
2208+
socket.on("connect_error", err => {
2209+
expect(err).to.be.an(Error);
2210+
expect(err.message).to.eql("Authentication error");
2211+
expect(err.data).to.eql({ a: "b", c: 3 });
21892212
done();
21902213
});
21912214
});

0 commit comments

Comments
 (0)