Compare commits

..

6 Commits
4.7.1 ... 4.7.2

Author SHA1 Message Date
Damien Arrachequesne
c332643ad8 chore(release): 4.7.2
Diff: https://github.com/socketio/socket.io/compare/4.7.1...4.7.2
2023-08-03 01:51:04 +02:00
Damien Arrachequesne
3468a197af fix(webtransport): properly handle WebTransport-only connections
A WebTransport-only connection has no `request` attribute, so we need
to handle that case.
2023-08-03 01:45:21 +02:00
Damien Arrachequesne
09d45491c4 chore: bump engine.io to version 6.5.2
Diff: https://github.com/socketio/engine.io/compare/6.5.0...6.5.2
Release notes: https://github.com/socketio/engine.io/releases/tag/6.5.2
2023-08-03 00:39:46 +02:00
Jaro
0731c0d2f4 fix: clean up child namespace when client is rejected in middleware (#4773)
Related: https://github.com/socketio/socket.io/issues/4772
2023-07-21 08:33:46 +02:00
Damien Arrachequesne
03046a64ad docs: update the list of supported Node.js versions
The Engine.IO server uses `timeout.refresh()` (see [1]), which was
added in Node.js 10.2.0.

Reference: https://nodejs.org/api/timers.html#timeoutrefresh

Related: https://github.com/socketio/engine.io/issues/686

[1]: 37474c7e67
2023-07-09 10:14:49 +02:00
Damien Arrachequesne
443e447087 docs(examples): add example with WebTransport 2023-06-29 11:21:27 +02:00
21 changed files with 449 additions and 93 deletions

View File

@@ -2,6 +2,7 @@
## 2023
- [4.7.2](#472-2023-08-02) (Aug 2023)
- [4.7.1](#471-2023-06-28) (Jun 2023)
- [4.7.0](#470-2023-06-22) (Jun 2023)
- [4.6.2](#462-2023-05-31) (May 2023)
@@ -60,6 +61,23 @@
# Release notes
## [4.7.2](https://github.com/socketio/socket.io/compare/4.7.1...4.7.2) (2023-08-02)
### Bug Fixes
* clean up child namespace when client is rejected in middleware ([#4773](https://github.com/socketio/socket.io/issues/4773)) ([0731c0d](https://github.com/socketio/socket.io/commit/0731c0d2f497d5cce596ea1ec32a67c08bcccbcd))
* **webtransport:** properly handle WebTransport-only connections ([3468a19](https://github.com/socketio/socket.io/commit/3468a197afe87e65eb0d779fabd347fe683013ab))
* **webtransport:** add proper framing ([a306db0](https://github.com/socketio/engine.io/commit/a306db09e8ddb367c7d62f45fec920f979580b7c))
### Dependencies
- [`engine.io@~6.5.2`](https://github.com/socketio/engine.io/releases/tag/6.5.2) ([diff](https://github.com/socketio/engine.io/compare/6.5.0...6.5.2))
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)
## [4.7.1](https://github.com/socketio/socket.io/compare/4.7.0...4.7.1) (2023-06-28)
The client bundle contains a few fixes regarding the WebTransport support.

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,5 +1,5 @@
/*!
* Socket.IO v4.7.1
* Socket.IO v4.7.2
* (c) 2014-2023 Guillermo Rauch
* Released under the MIT License.
*/
@@ -466,16 +466,124 @@
}
return packets;
};
function createPacketEncoderStream() {
return new TransformStream({
transform: function transform(packet, controller) {
encodePacketToBinary(packet, function (encodedPacket) {
var payloadLength = encodedPacket.length;
var header;
// inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
if (payloadLength < 126) {
header = new Uint8Array(1);
new DataView(header.buffer).setUint8(0, payloadLength);
} else if (payloadLength < 65536) {
header = new Uint8Array(3);
var view = new DataView(header.buffer);
view.setUint8(0, 126);
view.setUint16(1, payloadLength);
} else {
header = new Uint8Array(9);
var _view = new DataView(header.buffer);
_view.setUint8(0, 127);
_view.setBigUint64(1, BigInt(payloadLength));
}
// first bit indicates whether the payload is plain text (0) or binary (1)
if (packet.data && typeof packet.data !== "string") {
header[0] |= 0x80;
}
controller.enqueue(header);
controller.enqueue(encodedPacket);
});
}
});
}
var TEXT_DECODER;
function decodePacketFromBinary(data, isBinary, binaryType) {
function totalLength(chunks) {
return chunks.reduce(function (acc, chunk) {
return acc + chunk.length;
}, 0);
}
function concatChunks(chunks, size) {
if (chunks[0].length === size) {
return chunks.shift();
}
var buffer = new Uint8Array(size);
var j = 0;
for (var i = 0; i < size; i++) {
buffer[i] = chunks[0][j++];
if (j === chunks[0].length) {
chunks.shift();
j = 0;
}
}
if (chunks.length && j < chunks[0].length) {
chunks[0] = chunks[0].slice(j);
}
return buffer;
}
function createPacketDecoderStream(maxPayload, binaryType) {
if (!TEXT_DECODER) {
// lazily created for compatibility with old browser platforms
TEXT_DECODER = new TextDecoder();
}
// 48 === "0".charCodeAt(0) (OPEN packet type)
// 54 === "6".charCodeAt(0) (NOOP packet type)
var isPlainBinary = isBinary || data[0] < 48 || data[0] > 54;
return decodePacket(isPlainBinary ? data : TEXT_DECODER.decode(data), binaryType);
var chunks = [];
var state = 0 /* READ_HEADER */;
var expectedLength = -1;
var isBinary = false;
return new TransformStream({
transform: function transform(chunk, controller) {
chunks.push(chunk);
while (true) {
if (state === 0 /* READ_HEADER */) {
if (totalLength(chunks) < 1) {
break;
}
var header = concatChunks(chunks, 1);
isBinary = (header[0] & 0x80) === 0x80;
expectedLength = header[0] & 0x7f;
if (expectedLength < 126) {
state = 3 /* READ_PAYLOAD */;
} else if (expectedLength === 126) {
state = 1 /* READ_EXTENDED_LENGTH_16 */;
} else {
state = 2 /* READ_EXTENDED_LENGTH_64 */;
}
} else if (state === 1 /* READ_EXTENDED_LENGTH_16 */) {
if (totalLength(chunks) < 2) {
break;
}
var headerArray = concatChunks(chunks, 2);
expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
state = 3 /* READ_PAYLOAD */;
} else if (state === 2 /* READ_EXTENDED_LENGTH_64 */) {
if (totalLength(chunks) < 8) {
break;
}
var _headerArray = concatChunks(chunks, 8);
var view = new DataView(_headerArray.buffer, _headerArray.byteOffset, _headerArray.length);
var n = view.getUint32(0);
if (n > Math.pow(2, 53 - 32) - 1) {
// the maximum safe integer in JavaScript is 2^53 - 1
controller.enqueue(ERROR_PACKET);
break;
}
expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
state = 3 /* READ_PAYLOAD */;
} else {
if (totalLength(chunks) < expectedLength) {
break;
}
var data = concatChunks(chunks, expectedLength);
controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
state = 0 /* READ_HEADER */;
}
if (expectedLength === 0 || expectedLength > maxPayload) {
controller.enqueue(ERROR_PACKET);
break;
}
}
}
});
}
var protocol$1 = 4;
@@ -1455,7 +1563,7 @@
} catch (err) {
return this.emitReserved("error", err);
}
this.ws.binaryType = this.socket.binaryType || defaultBinaryType;
this.ws.binaryType = this.socket.binaryType;
this.addEventListeners();
}
/**
@@ -1565,11 +1673,6 @@
return WS;
}(Transport);
function shouldIncludeBinaryHeader(packet, encoded) {
// 48 === "0".charCodeAt(0) (OPEN packet type)
// 54 === "6".charCodeAt(0) (NOOP packet type)
return packet.type === "message" && typeof packet.data !== "string" && encoded[0] >= 48 && encoded[0] <= 54;
}
var WT = /*#__PURE__*/function (_Transport) {
_inherits(WT, _Transport);
var _super = _createSuper(WT);
@@ -1600,9 +1703,11 @@
// note: we could have used async/await, but that would require some additional polyfills
this.transport.ready.then(function () {
_this.transport.createBidirectionalStream().then(function (stream) {
var reader = stream.readable.getReader();
_this.writer = stream.writable.getWriter();
var binaryFlag;
var decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, _this.socket.binaryType);
var reader = stream.readable.pipeThrough(decoderStream).getReader();
var encoderStream = createPacketEncoderStream();
encoderStream.readable.pipeTo(stream.writable);
_this.writer = encoderStream.writable.getWriter();
var read = function read() {
reader.read().then(function (_ref) {
var done = _ref.done,
@@ -1610,19 +1715,18 @@
if (done) {
return;
}
if (!binaryFlag && value.byteLength === 1 && value[0] === 54) {
binaryFlag = true;
} else {
// TODO expose binarytype
_this.onPacket(decodePacketFromBinary(value, binaryFlag, "arraybuffer"));
binaryFlag = false;
}
_this.onPacket(value);
read();
})["catch"](function (err) {});
};
read();
var handshake = _this.query.sid ? "0{\"sid\":\"".concat(_this.query.sid, "\"}") : "0";
_this.writer.write(new TextEncoder().encode(handshake)).then(function () {
var packet = {
type: "open"
};
if (_this.query.sid) {
packet.data = "{\"sid\":\"".concat(_this.query.sid, "\"}");
}
_this.writer.write(packet).then(function () {
return _this.onOpen();
});
});
@@ -1636,18 +1740,13 @@
var _loop = function _loop() {
var packet = packets[i];
var lastPacket = i === packets.length - 1;
encodePacketToBinary(packet, function (data) {
if (shouldIncludeBinaryHeader(packet, data)) {
_this2.writer.write(Uint8Array.of(54));
_this2.writer.write(packet).then(function () {
if (lastPacket) {
nextTick(function () {
_this2.writable = true;
_this2.emitReserved("drain");
}, _this2.setTimeoutFn);
}
_this2.writer.write(data).then(function () {
if (lastPacket) {
nextTick(function () {
_this2.writable = true;
_this2.emitReserved("drain");
}, _this2.setTimeoutFn);
}
});
});
};
for (var i = 0; i < packets.length; i++) {
@@ -1749,6 +1848,7 @@
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, Socket);
_this = _super.call(this);
_this.binaryType = defaultBinaryType;
_this.writeBuffer = [];
if (uri && "object" === _typeof(uri)) {
opts = uri;
@@ -2038,12 +2138,12 @@
this.emitReserved("packet", packet);
// Socket is live - any packet counts
this.emitReserved("heartbeat");
this.resetPingTimeout();
switch (packet.type) {
case "open":
this.onHandshake(JSON.parse(packet.data));
break;
case "ping":
this.resetPingTimeout();
this.sendPacket("pong");
this.emitReserved("ping");
this.emitReserved("pong");

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

1
examples/webtransport/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.pem

View File

@@ -0,0 +1,18 @@
# Socket.IO WebTransport example
## How to use
```shell
# generate a self-signed certificate
$ ./generate_cert.sh
# install dependencies
$ npm i
# start the server
$ node index.js
# open a Chrome browser
$ ./open_chrome.sh
```

View File

@@ -0,0 +1,8 @@
#!/bin/bash
openssl req -new -x509 -nodes \
-out cert.pem \
-keyout key.pem \
-newkey ec \
-pkeyopt ec_paramgen_curve:prime256v1 \
-subj '/CN=127.0.0.1' \
-days 14

View File

@@ -0,0 +1,35 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Socket.IO WebTransport exampleqg</title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io({
transportOptions: {
webtransport: {
hostname: "127.0.0.1"
}
}
});
socket.on("connect", () => {
console.log(`connect ${socket.id}`);
socket.io.engine.on("upgrade", (transport) => {
console.log(`transport upgraded to ${transport.name}`);
});
});
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
socket.on("disconnect", (reason) => {
console.log(`disconnect due to ${reason}`);
});
</script>
</body>
</html>

View File

@@ -0,0 +1,68 @@
import { readFileSync } from "node:fs";
import { createServer } from "node:https";
import { Server } from "socket.io";
import { Http3Server } from "@fails-components/webtransport";
const key = readFileSync("./key.pem");
const cert = readFileSync("./cert.pem");
const httpsServer = createServer({
key,
cert
}, (req, res) => {
if (req.method === "GET" && req.url === "/") {
const content = readFileSync("./index.html");
res.writeHead(200, {
"content-type": "text/html"
});
res.write(content);
res.end();
} else {
res.writeHead(404).end();
}
});
const io = new Server(httpsServer, {
transports: ["polling", "websocket", "webtransport"]
});
const port = process.env.PORT || 3000;
io.on("connection", (socket) => {
console.log(`connect ${socket.id}`);
socket.conn.on("upgrade", (transport) => {
console.log(`transport upgraded to ${transport.name}`);
});
socket.on("disconnect", (reason) => {
console.log(`disconnect ${socket.id} due to ${reason}`);
});
});
httpsServer.listen(port, () => {
console.log(`server listening at https://localhost:${port}`);
});
const h3Server = new Http3Server({
port,
host: "0.0.0.0",
secret: "changeit",
cert,
privKey: key,
});
(async () => {
const stream = await h3Server.sessionStream("/socket.io/");
const sessionReader = stream.getReader();
while (true) {
const { done, value } = await sessionReader.read();
if (done) {
break;
}
io.engine.onWebTransportSession(value);
}
})();
h3Server.startServer();

View File

@@ -0,0 +1,10 @@
#!/bin/bash
HASH=`openssl x509 -pubkey -noout -in cert.pem |
openssl pkey -pubin -outform der |
openssl dgst -sha256 -binary |
base64`
/opt/google/chrome/chrome \
--origin-to-force-quic-on=127.0.0.1:3000 \
--ignore-certificate-errors-spki-list=$HASH \
https://localhost:3000

View File

@@ -0,0 +1,11 @@
{
"name": "webtransport",
"version": "0.0.1",
"description": "",
"private": true,
"type": "module",
"dependencies": {
"@fails-components/webtransport": "^0.1.7",
"socket.io": "^4.7.1"
}
}

View File

@@ -292,16 +292,16 @@ export class Socket<
*/
private buildHandshake(auth: object): Handshake {
return {
headers: this.request.headers,
headers: this.request?.headers || {},
time: new Date() + "",
address: this.conn.remoteAddress,
xdomain: !!this.request.headers.origin,
xdomain: !!this.request?.headers.origin,
// @ts-ignore
secure: !!this.request.connection.encrypted,
secure: !this.request || !!this.request.connection.encrypted,
issued: +new Date(),
url: this.request.url!,
url: this.request?.url!,
// @ts-ignore
query: this.request._query,
query: this.request?._query || {},
auth,
};
}
@@ -758,7 +758,6 @@ export class Socket<
}
this._cleanup();
this.nsp._remove(this);
this.client._remove(this);
this.connected = false;
this.emitReserved("disconnect", reason, description);
@@ -772,6 +771,7 @@ export class Socket<
*/
_cleanup() {
this.leaveAll();
this.nsp._remove(this);
this.join = noop;
}

72
package-lock.json generated
View File

@@ -1,19 +1,19 @@
{
"name": "socket.io",
"version": "4.7.0",
"version": "4.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "socket.io",
"version": "4.7.0",
"version": "4.7.1",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"cors": "~2.8.5",
"debug": "~4.3.2",
"engine.io": "~6.5.0",
"engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},
@@ -24,7 +24,7 @@
"nyc": "^15.1.0",
"prettier": "^2.3.2",
"rimraf": "^3.0.2",
"socket.io-client": "4.7.1",
"socket.io-client": "4.7.2",
"socket.io-client-v2": "npm:socket.io-client@^2.4.0",
"superagent": "^8.0.0",
"supertest": "^6.1.6",
@@ -34,7 +34,7 @@
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.30.0"
},
"engines": {
"node": ">=10.0.0"
"node": ">=10.2.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -1378,9 +1378,9 @@
"dev": true
},
"node_modules/engine.io": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.0.tgz",
"integrity": "sha512-UlfoK1iD62Hkedw2TmuHdhDsZCGaAyp+LZ/AvnImjYBeWagA3qIEETum90d6shMeFZiDuGT66zVCdx1wKYKGGg==",
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz",
"integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==",
"dependencies": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
@@ -1390,30 +1390,30 @@
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.1.0",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0"
},
"engines": {
"node": ">=10.0.0"
"node": ">=10.2.0"
}
},
"node_modules/engine.io-client": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.1.tgz",
"integrity": "sha512-hE5wKXH8Ru4L19MbM1GgYV/2Qo54JSMh1rlJbfpa40bEWkCKNo3ol2eOtGmowcr+ysgbI7+SGL+by42Q3pt/Ng==",
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.2.tgz",
"integrity": "sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.1.0",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-parser": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
"integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w==",
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==",
"engines": {
"node": ">=10.0.0"
}
@@ -3464,14 +3464,14 @@
}
},
"node_modules/socket.io-client": {
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.1.tgz",
"integrity": "sha512-Qk3Xj8ekbnzKu3faejo4wk2MzXA029XppiXtTF/PkbTg+fcwaTw1PlDrTrrrU4mKoYC4dvlApOnSeyLCKwek2w==",
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz",
"integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.1",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
@@ -5388,9 +5388,9 @@
"dev": true
},
"engine.io": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.0.tgz",
"integrity": "sha512-UlfoK1iD62Hkedw2TmuHdhDsZCGaAyp+LZ/AvnImjYBeWagA3qIEETum90d6shMeFZiDuGT66zVCdx1wKYKGGg==",
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz",
"integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==",
"requires": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
@@ -5400,27 +5400,27 @@
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.1.0",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0"
}
},
"engine.io-client": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.1.tgz",
"integrity": "sha512-hE5wKXH8Ru4L19MbM1GgYV/2Qo54JSMh1rlJbfpa40bEWkCKNo3ol2eOtGmowcr+ysgbI7+SGL+by42Q3pt/Ng==",
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.2.tgz",
"integrity": "sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.1.0",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"engine.io-parser": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
"integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w=="
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ=="
},
"error-ex": {
"version": "1.3.2",
@@ -6923,14 +6923,14 @@
}
},
"socket.io-client": {
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.1.tgz",
"integrity": "sha512-Qk3Xj8ekbnzKu3faejo4wk2MzXA029XppiXtTF/PkbTg+fcwaTw1PlDrTrrrU4mKoYC4dvlApOnSeyLCKwek2w==",
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz",
"integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.1",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "socket.io",
"version": "4.7.1",
"version": "4.7.2",
"description": "node.js realtime framework server",
"keywords": [
"realtime",
@@ -50,7 +50,7 @@
"base64id": "~2.0.0",
"cors": "~2.8.5",
"debug": "~4.3.2",
"engine.io": "~6.5.0",
"engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},
@@ -61,7 +61,7 @@
"nyc": "^15.1.0",
"prettier": "^2.3.2",
"rimraf": "^3.0.2",
"socket.io-client": "4.7.1",
"socket.io-client": "4.7.2",
"socket.io-client-v2": "npm:socket.io-client@^2.4.0",
"superagent": "^8.0.0",
"supertest": "^6.1.6",
@@ -89,7 +89,7 @@
}
],
"engines": {
"node": ">=10.0.0"
"node": ">=10.2.0"
},
"tsd": {
"directory": "test"

View File

@@ -653,6 +653,76 @@ describe("namespaces", () => {
io.of(/^\/dynamic-\d+$/);
});
it("should NOT clean up namespace when cleanupEmptyChildNamespaces is OFF and client is rejected in middleware", (done) => {
const io = new Server(0, { cleanupEmptyChildNamespaces: false });
io.of(/^\/dynamic-\d+$/).use((socket, next) => {
next(new Error("You shall not pass!"));
});
const c1 = createClient(io, "/dynamic-101");
c1.on("connect", () => {
done(new Error("Should not connect"));
});
c1.on("connect_error", () => {
setTimeout(() => {
expect(io._nsps.has("/dynamic-101")).to.be(true);
expect(io._nsps.get("/dynamic-101")!.sockets.size).to.be(0);
success(done, io, c1);
}, 100);
});
});
it("should clean up namespace when cleanupEmptyChildNamespaces is ON and client is rejected in middleware", (done) => {
const io = new Server(0, { cleanupEmptyChildNamespaces: true });
io.of(/^\/dynamic-\d+$/).use((socket, next) => {
next(new Error("You shall not pass!"));
});
const c1 = createClient(io, "/dynamic-101");
c1.on("connect", () => {
done(new Error("Should not connect"));
});
c1.on("connect_error", () => {
setTimeout(() => {
expect(io._nsps.has("/dynamic-101")).to.be(false);
success(done, io, c1);
}, 100);
});
});
it("should NOT clean up namespace when cleanupEmptyChildNamespaces is ON and client is rejected in middleware but there are other clients connected", (done) => {
const io = new Server(0, { cleanupEmptyChildNamespaces: true });
let clientIdxToReject = 0;
io.of(/^\/dynamic-\d+$/).use((socket, next) => {
if (clientIdxToReject) {
next(new Error("You shall not pass!"));
} else {
next();
}
clientIdxToReject++;
});
const c1 = createClient(io, "/dynamic-101");
c1.on("connect", () => {
const c2 = createClient(io, "/dynamic-101");
c2.on("connect", () => {
done(new Error("Client 2 should not connect"));
});
c2.on("connect_error", () => {
setTimeout(() => {
expect(io._nsps.has("/dynamic-101")).to.be(true);
expect(io._nsps.get("/dynamic-101")!.sockets.size).to.be(1);
success(done, io, c1, c2);
}, 100);
});
});
c1.on("connect_error", () => {
done(new Error("Client 1 should not get an error"));
});
});
it("should attach a child namespace to its parent upon manual creation", () => {
const io = new Server(0);
const parentNamespace = io.of(/^\/dynamic-\d+$/);

View File

@@ -684,6 +684,23 @@ describe("socket", () => {
});
});
it("should handshake a client without access to the Engine.IO request (WebTransport-only connection)", (done) => {
const io = new Server(0);
const clientSocket = createClient(io, "/");
io.engine.on("connection", (socket) => {
delete socket.request;
});
io.on("connection", (socket) => {
expect(socket.handshake.secure).to.be(true);
expect(socket.handshake.headers).to.eql({});
expect(socket.handshake.query).to.eql({});
success(done, io, clientSocket);
});
});
it("should handle very large json", function (done) {
this.timeout(30000);
const io = new Server(0, { perMessageDeflate: false });