Compare commits

..

4 Commits

Author SHA1 Message Date
Damien Arrachequesne
02951c4391 chore(release): 3.0.0-rc4
Diff: https://github.com/socketio/socket.io/compare/3.0.0-rc3...3.0.0-rc4
2020-10-30 23:02:43 +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
64056d6616 docs(examples): update TypeScript example 2020-10-27 22:18:07 +01:00
15 changed files with 116 additions and 81 deletions

View File

@@ -1,3 +1,13 @@
# [3.0.0-rc4](https://github.com/socketio/socket.io/compare/3.0.0-rc3...3.0.0-rc4) (2020-10-30)
### Features
* emit an Error object upon middleware error ([54bf4a4](https://github.com/socketio/socket.io/commit/54bf4a44e9e896dfb64764ee7bd4e8823eb7dc7b))
* serve msgpack bundle ([aa7574f](https://github.com/socketio/socket.io/commit/aa7574f88471aa30ae472a5cddf1000a8baa70fd))
# [3.0.0-rc3](https://github.com/socketio/socket.io/compare/3.0.0-rc2...3.0.0-rc3) (2020-10-26)

View File

@@ -1,5 +1,5 @@
/*!
* Socket.IO v3.0.0-rc3
* Socket.IO v3.0.0-rc4
* (c) 2014-2020 Guillermo Rauch
* Released under the MIT License.
*/
@@ -416,14 +416,14 @@ var Manager = /*#__PURE__*/function (_Emitter) {
var openSub = on_1.on(socket, "open", function () {
self.onopen();
fn && fn();
}); // emit `connect_error`
}); // emit `error`
var errorSub = on_1.on(socket, "error", function (err) {
debug("connect_error");
debug("error");
self.cleanup();
self._readyState = "closed";
_get(_getPrototypeOf(Manager.prototype), "emit", _this2).call(_this2, "connect_error", err);
_get(_getPrototypeOf(Manager.prototype), "emit", _this2).call(_this2, "error", err);
if (fn) {
fn(err);
@@ -431,7 +431,7 @@ var Manager = /*#__PURE__*/function (_Emitter) {
// Only do this if there is no fn to handle the error
self.maybeReconnectOnOpen();
}
}); // emit `connect_timeout`
});
if (false !== this._timeout) {
var timeout = this._timeout;
@@ -446,9 +446,7 @@ var Manager = /*#__PURE__*/function (_Emitter) {
debug("connect attempt timed out after %d", timeout);
openSub.destroy();
socket.close();
socket.emit("error", "timeout");
_get(_getPrototypeOf(Manager.prototype), "emit", _this2).call(_this2, "connect_error", new Error("timeout"));
socket.emit("error", new Error("timeout"));
}, timeout);
this.subs.push({
destroy: function destroy() {
@@ -712,9 +710,7 @@ var Manager = /*#__PURE__*/function (_Emitter) {
if (self.skipReconnect) return;
debug("attempting reconnect");
_get(_getPrototypeOf(Manager.prototype), "emit", _this3).call(_this3, "reconnect_attempt", self.backoff.attempts);
_get(_getPrototypeOf(Manager.prototype), "emit", _this3).call(_this3, "reconnecting", self.backoff.attempts); // check again for the case socket closed in above events
_get(_getPrototypeOf(Manager.prototype), "emit", _this3).call(_this3, "reconnect_attempt", self.backoff.attempts); // check again for the case socket closed in above events
if (self.skipReconnect) return;
@@ -1103,7 +1099,11 @@ var Socket = /*#__PURE__*/function (_Emitter) {
break;
case socket_io_parser_1.PacketType.CONNECT_ERROR:
_get(_getPrototypeOf(Socket.prototype), "emit", this).call(this, "connect_error", packet.data);
var err = new Error(packet.data.message); // @ts-ignore
err.data = packet.data.data;
_get(_getPrototypeOf(Socket.prototype), "emit", this).call(this, "connect_error", err);
break;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,14 +1,12 @@
import { Manager } from "socket.io-client";
const manager = new Manager("ws://localhost:8080", {});
const manager = new Manager("ws://localhost:8080");
const socket = manager.socket("/");
// @ts-ignore
socket.on("connect", () => {
console.log(`connect ${socket.id}`);
});
// @ts-ignore
socket.on("disconnect", () => {
console.log(`disconnect`);
});

View File

@@ -38,24 +38,11 @@
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
},
"better-assert": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
"integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
"requires": {
"callsite": "1.0.0"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
"integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
},
"component-bind": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
@@ -94,9 +81,9 @@
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
},
"engine.io": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.0.0.tgz",
"integrity": "sha512-WyTa1NJR8rRmPXGXNSSgA+XhzfYLVcRBjRoFx7gI3cARnEsyuMpg0PS/PMDnPMMQtkjmVZsi2/ETrpq4mhoYSw==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.0.1.tgz",
"integrity": "sha512-6EaSBxasBUwxRdf6B68SEYpD3tcrG80J4YTzHl/D+9Q+vM0AMHZabfYcc2WdnvEaQxZjX/UZsa+UdGoM0qQQkQ==",
"requires": {
"accepts": "~1.3.4",
"base64id": "2.0.0",
@@ -108,9 +95,9 @@
}
},
"engine.io-client": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.0.0.tgz",
"integrity": "sha512-dmydBrbZW0AYX4+u7aRzslPw/MSZy3HwwqHx3Es5OPj9q0tnyPeFZZU/UE5aLjba6xIwZTXkB+OdqF5wmR21IA==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.0.1.tgz",
"integrity": "sha512-3XXfWrEutlf1vg5PlS805bD+AgZXhRIKYAG04f1iCGOs70dWEYlZGfCZUNwPwNx05lBCKs1lIeL3SkLB0P++xw==",
"requires": {
"base64-arraybuffer": "0.1.4",
"component-emitter": "~1.3.0",
@@ -118,20 +105,12 @@
"engine.io-parser": "~4.0.1",
"has-cors": "1.1.0",
"parseqs": "0.0.6",
"parseuri": "0.0.5",
"parseuri": "0.0.6",
"ws": "~7.2.1",
"xmlhttprequest-ssl": "~1.5.4",
"yeast": "0.1.2"
},
"dependencies": {
"parseuri": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
"integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
"requires": {
"better-assert": "~1.0.0"
}
},
"ws": {
"version": "7.2.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
@@ -193,27 +172,27 @@
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
},
"socket.io": {
"version": "3.0.0-rc2",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.0.0-rc2.tgz",
"integrity": "sha512-viH824jjAF+tCN6zfFgZR9wsgXWZ6zuVZ46ZQDsThyXdkv6+RihAZ/xz6LqsP8vFK83MVtRztMAIc56eyeKX0g==",
"version": "3.0.0-rc3",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.0.0-rc3.tgz",
"integrity": "sha512-AVIpRd7OTyhCgg5muz0AqeF06csptsnP8UP10ubLrnL7XKplJFDadUB9fEbwB3iLMpf1NT+YfqTBCVKHhpMlZA==",
"requires": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"debug": "~4.1.0",
"engine.io": "~4.0.0",
"socket.io-adapter": "2.0.3-rc1",
"socket.io-client": "3.0.0-rc2",
"socket.io-parser": "4.0.1-rc2"
"socket.io-adapter": "2.0.3-rc2",
"socket.io-parser": "4.0.1-rc3"
}
},
"socket.io-adapter": {
"version": "2.0.3-rc1",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.0.3-rc1.tgz",
"integrity": "sha512-/+irxVkiriDRMt2hcYYlDOl2LUU3wkjPQ1917t/hb617/W+bnlDaqEGqtQpFE/tWys5FI1+q2JnjdwNeRHxyNw=="
"version": "2.0.3-rc2",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.0.3-rc2.tgz",
"integrity": "sha512-ic/fttwhpQ2Ry43ou6gOIeZgpGmsIUFQZ0Ww0DIpCerTKzDdLPG2+AEomG5SGXpppvtbwwesB7O9Azq0JiSs/g=="
},
"socket.io-client": {
"version": "3.0.0-rc2",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.0.0-rc2.tgz",
"integrity": "sha512-ZIVzV1ANogp5ZqkIn504UhD4NwZkCWLoq9/rHiNSI0RIsvsfGxyOzhNvr0fWPppfr8+hNt5Qbij6ucV5ijIJDg==",
"version": "3.0.0-rc3",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.0.0-rc3.tgz",
"integrity": "sha512-9w67FZtTsGlDiwpobQ0l1UeLinx6LuFYEHGTcFRc5P5PyY/4M6ZI7nBFxIhjf0l8DTUfAJwllqzNxSqMW5nxhw==",
"requires": {
"@types/component-emitter": "^1.2.10",
"backo2": "1.0.2",
@@ -222,13 +201,13 @@
"debug": "~4.1.0",
"engine.io-client": "~4.0.0",
"parseuri": "0.0.6",
"socket.io-parser": "4.0.1-rc2"
"socket.io-parser": "4.0.1-rc3"
}
},
"socket.io-parser": {
"version": "4.0.1-rc2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.1-rc2.tgz",
"integrity": "sha512-aI20UWITf5vKgwA1HjCanYlM8cr2VDmOBiM3+1MM1MautnHAngiceuN0gUOtQs4MmWatuD2Td8g00EwHf3qthQ==",
"version": "4.0.1-rc3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.1-rc3.tgz",
"integrity": "sha512-H85dvTVUOBMzquX5AojQvxRPCvH7jMkrhp2la+2gYn/uiS20sK1U8osWCMwU00oUITDUkjDTxLjw0fGkDTA76w==",
"requires": {
"component-emitter": "~1.3.0",
"debug": "~4.1.0"

View File

@@ -1,8 +1,8 @@
import { Server } from "socket.io";
import { Server, Socket } from "socket.io";
const io = new Server(8080);
io.on("connect", (socket) => {
io.on("connect", (socket: Socket) => {
console.log(`connect ${socket.id}`);
socket.on("ping", (cb) => {

View File

@@ -93,7 +93,9 @@ export class Client {
this._packet({
type: PacketType.CONNECT_ERROR,
nsp: name,
data: "Invalid namespace"
data: {
message: "Invalid namespace"
}
});
}
});

View File

@@ -7,7 +7,7 @@ import path from "path";
import engine from "engine.io";
import { Client } from "./client";
import { EventEmitter } from "events";
import { Namespace } from "./namespace";
import { ExtendedError, Namespace } from "./namespace";
import { ParentNamespace } from "./parent-namespace";
import { Adapter, Room, SocketId } from "socket.io-adapter";
import * as parser from "socket.io-parser";
@@ -272,7 +272,9 @@ export class Server extends EventEmitter {
const escapedPath = this._path.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
this.clientPathRegex = new RegExp(
"^" + escapedPath + "/socket\\.io(\\.min)?\\.js(\\.map)?$"
"^" +
escapedPath +
"/socket\\.io(\\.min|\\.msgpack\\.min)?\\.js(\\.map)?$"
);
return this;
}
@@ -591,7 +593,7 @@ export class Server extends EventEmitter {
* @public
*/
public use(
fn: (socket: Socket, next: (err?: Error) => void) => void
fn: (socket: Socket, next: (err?: ExtendedError) => void) => void
): Server {
this.sockets.use(fn);
return this;

View File

@@ -8,6 +8,10 @@ import { Adapter, Room, SocketId } from "socket.io-adapter";
const debug = debugModule("socket.io:namespace");
export interface ExtendedError extends Error {
data?: any;
}
export class Namespace extends EventEmitter {
public readonly name: string;
public readonly sockets: Map<SocketId, Socket> = new Map();
@@ -18,7 +22,9 @@ export class Namespace extends EventEmitter {
readonly server: Server;
/** @private */
_fns: Array<(socket: Socket, next: (err: Error) => void) => void> = [];
_fns: Array<
(socket: Socket, next: (err: ExtendedError) => void) => void
> = [];
/** @private */
_rooms: Set<Room> = new Set();
@@ -60,7 +66,7 @@ export class Namespace extends EventEmitter {
* @public
*/
public use(
fn: (socket: Socket, next: (err?: Error) => void) => void
fn: (socket: Socket, next: (err?: ExtendedError) => void) => void
): Namespace {
this._fns.push(fn);
return this;
@@ -73,7 +79,7 @@ export class Namespace extends EventEmitter {
* @param {Function} fn - last fn call in the middleware
* @private
*/
private run(socket: Socket, fn: (err: Error) => void) {
private run(socket: Socket, fn: (err: ExtendedError) => void) {
const fns = this._fns.slice(0);
if (!fns.length) return fn(null);
@@ -129,7 +135,11 @@ export class Namespace extends EventEmitter {
this.run(socket, err => {
process.nextTick(() => {
if ("open" == client.conn.readyState) {
if (err) return socket._error(err.message);
if (err)
return socket._error({
message: err.message,
data: err.data
});
// track socket
this.sockets.set(socket.id, socket);

View File

@@ -1,6 +1,6 @@
{
"name": "socket.io",
"version": "3.0.0-rc3",
"version": "3.0.0-rc4",
"description": "node.js realtime framework server",
"keywords": [
"realtime",
@@ -13,6 +13,7 @@
],
"files": [
"dist/",
"client-dist/",
"wrapper.mjs"
],
"type": "commonjs",
@@ -53,7 +54,7 @@
"mocha": "^3.5.3",
"nyc": "^11.2.1",
"prettier": "^1.19.1",
"socket.io-client": "3.0.0-rc3",
"socket.io-client": "3.0.0-rc4",
"superagent": "^3.8.2",
"supertest": "^3.0.0",
"ts-node": "^9.0.0",

View File

@@ -92,6 +92,16 @@ describe("socket.io", () => {
});
});
it(
"should serve bundle with msgpack parser",
testSource("socket.io.msgpack.min.js")
);
it(
"should serve source map for bundle with msgpack parser",
testSourceMap("socket.io.msgpack.min.js.map")
);
it("should handle 304", done => {
const srv = createServer();
new Server(srv);
@@ -512,7 +522,7 @@ describe("socket.io", () => {
srv.listen(() => {
const socket = client(srv, "/doesnotexist");
socket.on("connect_error", err => {
expect(err).to.be("Invalid namespace");
expect(err.message).to.be("Invalid namespace");
done();
});
});
@@ -804,7 +814,7 @@ describe("socket.io", () => {
sio.of(/^\/dynamic-\d+$/);
sio.of((name, query, next) => next(null, "/dynamic-101" === name));
socket.on("connect_error", err => {
expect(err).to.be("Invalid namespace");
expect(err.message).to.be("Invalid namespace");
done();
});
});
@@ -2175,7 +2185,30 @@ describe("socket.io", () => {
done(new Error("nope"));
});
socket.on("connect_error", err => {
expect(err).to.be("Authentication error");
expect(err.message).to.be("Authentication error");
done();
});
});
});
it("should pass an object", done => {
const srv = createServer();
const sio = new Server(srv);
sio.use((socket, next) => {
const err = new Error("Authentication error");
// @ts-ignore
err.data = { a: "b", c: 3 };
next(err);
});
srv.listen(() => {
const socket = client(srv);
socket.on("connect", () => {
done(new Error("nope"));
});
socket.on("connect_error", err => {
expect(err).to.be.an(Error);
expect(err.message).to.eql("Authentication error");
expect(err.data).to.eql({ a: "b", c: 3 });
done();
});
});