Compare commits

..

15 Commits
4.6.2 ... 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
Damien Arrachequesne
2f6cc2fa42 chore(release): 4.7.1
Diff: https://github.com/socketio/socket.io/compare/4.7.0...4.7.1
2023-06-28 09:32:32 +02:00
Damien Arrachequesne
00d8ee5b05 chore(release): 4.7.0
Diff: https://github.com/socketio/socket.io/compare/4.6.2...4.7.0
2023-06-22 11:27:45 +02:00
Damien Arrachequesne
2dd5fa9dd4 ci: add Node.js 20 in the test matrix
Reference: https://github.com/nodejs/Release
2023-06-22 07:55:32 +02:00
Damien Arrachequesne
a5dff0ac83 docs(examples): increase httpd ProxyTimeout value (2) 2023-06-21 00:07:44 +02:00
Damien Arrachequesne
3035c25982 docs(examples): increase httpd ProxyTimeout value
With a value that is too small, the HTTP long-polling request receives
an HTTP 502 response code and the connection gets closed.
2023-06-20 23:57:46 +02:00
Damien Arrachequesne
63f181cc12 feat: serve client bundles with CORS headers
The version of the `cors` package matches the one used by `engine.io`.

Related: https://github.com/socketio/socket.io/issues/3552
2023-06-20 14:32:59 +02:00
Damien Arrachequesne
a250e283da chore: bump engine.io to version 6.5.0
Diff: https://github.com/socketio/engine.io/compare/6.4.2...6.5.0
Release notes: https://github.com/socketio/engine.io/releases/tag/6.5.0
2023-06-20 09:17:10 +02:00
SyedTayyabUlMazhar
e5c62cad60 fix: remove the Partial modifier from the socket.data type (#4740)
Wrapping SocketData with Partial causes issues when reading data even
if you've made sure to pass all values. If someone want to make their
type Partial or make only a few properties optional, they can do so in
their own type instead.

Related: https://github.com/socketio/socket.io/issues/4537
2023-06-20 07:49:02 +02:00
Damien Arrachequesne
01d37624a8 docs(changelog): update the version range of the engine.io dependency 2023-05-31 11:28:00 +02:00
25 changed files with 1043 additions and 1012 deletions

View File

@@ -16,7 +16,9 @@ jobs:
strategy:
matrix:
node-version: [12, 14, 16]
node-version:
- 16
- 20
steps:
- name: Checkout repository

View File

@@ -2,6 +2,9 @@
## 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)
- [4.6.1](#461-2023-02-20) (Feb 2023)
- [4.6.0](#460-2023-02-07) (Feb 2023)
@@ -58,6 +61,120 @@
# 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.
### Dependencies
- [`engine.io@~6.5.0`](https://github.com/socketio/engine.io/releases/tag/6.5.0) (no change)
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)
## [4.7.0](https://github.com/socketio/socket.io/compare/4.6.2...4.7.0) (2023-06-22)
### Bug Fixes
* remove the Partial modifier from the socket.data type ([#4740](https://github.com/socketio/socket.io/issues/4740)) ([e5c62ca](https://github.com/socketio/socket.io/commit/e5c62cad60fc7d16fbb024fd9be1d1880f4e6f5f))
### Features
#### Support for WebTransport
The Socket.IO server can now use WebTransport as the underlying transport.
WebTransport is a web API that uses the HTTP/3 protocol as a bidirectional transport. It's intended for two-way communications between a web client and an HTTP/3 server.
References:
- https://w3c.github.io/webtransport/
- https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
- https://developer.chrome.com/articles/webtransport/
Until WebTransport support lands [in Node.js](https://github.com/nodejs/node/issues/38478), you can use the `@fails-components/webtransport` package:
```js
import { readFileSync } from "fs";
import { createServer } from "https";
import { Server } from "socket.io";
import { Http3Server } from "@fails-components/webtransport";
// WARNING: the total length of the validity period MUST NOT exceed two weeks (https://w3c.github.io/webtransport/#custom-certificate-requirements)
const cert = readFileSync("/path/to/my/cert.pem");
const key = readFileSync("/path/to/my/key.pem");
const httpsServer = createServer({
key,
cert
});
httpsServer.listen(3000);
const io = new Server(httpsServer, {
transports: ["polling", "websocket", "webtransport"] // WebTransport is not enabled by default
});
const h3Server = new Http3Server({
port: 3000,
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();
```
Added in [123b68c](https://github.com/socketio/engine.io/commit/123b68c04f9e971f59b526e0f967a488ee6b0116).
#### Client bundles with CORS headers
The bundles will now have the right `Access-Control-Allow-xxx` headers.
Added in [63f181c](https://github.com/socketio/socket.io/commit/63f181cc12cbbbf94ed40eef52d60f36a1214fbe).
### Dependencies
- [`engine.io@~6.5.0`](https://github.com/socketio/engine.io/releases/tag/6.5.0) ([diff](https://github.com/socketio/engine.io/compare/6.4.2...6.5.0))
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)
## [4.6.2](https://github.com/socketio/socket.io/compare/4.6.1...4.6.2) (2023-05-31)
@@ -68,7 +185,7 @@
### Dependencies
- [`engine.io@~6.4.0`](https://github.com/socketio/engine.io/releases/tag/6.4.0) (no change)
- [`engine.io@~6.4.2`](https://github.com/socketio/engine.io/releases/tag/6.4.0) ([diff](https://github.com/socketio/engine.io/compare/6.4.1...6.4.2))
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)
@@ -84,7 +201,7 @@
### Dependencies
- [`engine.io@~6.4.0`](https://github.com/socketio/engine.io/releases/tag/6.4.0) (no change)
- [`engine.io@~6.4.1`](https://github.com/socketio/engine.io/releases/tag/6.4.1) ([diff](https://github.com/socketio/engine.io/compare/6.4.0...6.4.1))
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)

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 it is too large Load Diff

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

@@ -51,4 +51,5 @@ RewriteRule /(.*) balancer://nodes_ws/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) balancer://nodes_polling/$1 [P,L]
ProxyTimeout 3
# must be bigger than pingInterval (25s by default) + pingTimeout (20s by default)
ProxyTimeout 60

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

@@ -40,6 +40,7 @@ import {
SecondArg,
} from "./typed-events";
import { patchAdapter, restoreAdapter, serveFile } from "./uws";
import corsMiddleware from "cors";
const debug = debugModule("socket.io:server");
@@ -202,6 +203,11 @@ export class Server<
*/
_connectTimeout: number;
private httpServer: http.Server | HTTPSServer | Http2SecureServer;
private _corsMiddleware: (
req: http.IncomingMessage,
res: http.ServerResponse,
next: () => void
) => void;
/**
* Server constructor.
@@ -267,6 +273,10 @@ export class Server<
this.attach(
srv as http.Server | HTTPSServer | Http2SecureServer | number
);
if (this.opts.cors) {
this._corsMiddleware = corsMiddleware(this.opts.cors);
}
}
get _opts() {
@@ -548,7 +558,13 @@ export class Server<
srv.removeAllListeners("request");
srv.on("request", (req, res) => {
if (this.clientPathRegex.test(req.url!)) {
this.serve(req, res);
if (this._corsMiddleware) {
this._corsMiddleware(req, res, () => {
this.serve(req, res);
});
} else {
this.serve(req, res);
}
} else {
for (let i = 0; i < evs.length; i++) {
evs[i].call(srv, req, res);

View File

@@ -202,7 +202,7 @@ export class Socket<
* Additional information that can be attached to the Socket instance and which will be used in the
* {@link Server.fetchSockets()} method.
*/
public data: Partial<SocketData> = {};
public data: SocketData = {} as SocketData;
/**
* Whether the socket is currently connected or not.
*
@@ -260,7 +260,7 @@ export class Socket<
this.id = previousSession.sid;
this.pid = previousSession.pid;
previousSession.rooms.forEach((room) => this.join(room));
this.data = previousSession.data as Partial<SocketData>;
this.data = previousSession.data as SocketData;
previousSession.missedPackets.forEach((packet) => {
this.packet({
type: PacketType.EVENT,
@@ -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;
}

83
package-lock.json generated
View File

@@ -1,18 +1,19 @@
{
"name": "socket.io",
"version": "4.6.2",
"version": "4.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "socket.io",
"version": "4.6.2",
"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.4.2",
"engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},
@@ -23,17 +24,17 @@
"nyc": "^15.1.0",
"prettier": "^2.3.2",
"rimraf": "^3.0.2",
"socket.io-client": "4.6.2",
"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",
"ts-node": "^10.2.1",
"tsd": "^0.21.0",
"typescript": "^4.4.2",
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.0.0"
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.30.0"
},
"engines": {
"node": ">=10.0.0"
"node": ">=10.2.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -1377,9 +1378,9 @@
"dev": true
},
"node_modules/engine.io": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz",
"integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==",
"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",
@@ -1389,30 +1390,30 @@
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.3",
"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.4.0",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz",
"integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==",
"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.0.3",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-parser": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==",
"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"
}
@@ -3463,14 +3464,14 @@
}
},
"node_modules/socket.io-client": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.2.tgz",
"integrity": "sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==",
"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.4.0",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
@@ -4105,8 +4106,8 @@
}
},
"node_modules/uWebSockets.js": {
"version": "20.0.0",
"resolved": "git+https://git@github.com/uNetworking/uWebSockets.js.git#4558ee00f9f1f686fffe1accbfc2e85b1af9c50f",
"version": "20.30.0",
"resolved": "git+https://git@github.com/uNetworking/uWebSockets.js.git#d39d4181daf5b670d44cbc1b18f8c28c85fd4142",
"dev": true
},
"node_modules/v8-compile-cache-lib": {
@@ -5387,9 +5388,9 @@
"dev": true
},
"engine.io": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz",
"integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==",
"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",
@@ -5399,27 +5400,27 @@
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.3",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0"
}
},
"engine.io-client": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz",
"integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==",
"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.0.3",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"engine.io-parser": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg=="
"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",
@@ -6922,14 +6923,14 @@
}
},
"socket.io-client": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.2.tgz",
"integrity": "sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==",
"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.4.0",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
}
},
@@ -7402,9 +7403,9 @@
"dev": true
},
"uWebSockets.js": {
"version": "git+https://git@github.com/uNetworking/uWebSockets.js.git#4558ee00f9f1f686fffe1accbfc2e85b1af9c50f",
"version": "git+https://git@github.com/uNetworking/uWebSockets.js.git#d39d4181daf5b670d44cbc1b18f8c28c85fd4142",
"dev": true,
"from": "uWebSockets.js@github:uNetworking/uWebSockets.js#v20.0.0"
"from": "uWebSockets.js@github:uNetworking/uWebSockets.js#v20.30.0"
},
"v8-compile-cache-lib": {
"version": "3.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "socket.io",
"version": "4.6.2",
"version": "4.7.2",
"description": "node.js realtime framework server",
"keywords": [
"realtime",
@@ -48,8 +48,9 @@
"dependencies": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"cors": "~2.8.5",
"debug": "~4.3.2",
"engine.io": "~6.4.2",
"engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},
@@ -60,14 +61,14 @@
"nyc": "^15.1.0",
"prettier": "^2.3.2",
"rimraf": "^3.0.2",
"socket.io-client": "4.6.2",
"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",
"ts-node": "^10.2.1",
"tsd": "^0.21.0",
"typescript": "^4.4.2",
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.0.0"
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.30.0"
},
"contributors": [
{
@@ -88,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

@@ -70,6 +70,27 @@ describe("server attachment", () => {
});
});
it("should serve client with necessary CORS headers", (done) => {
const srv = createServer();
new Server(srv, {
cors: {
origin: "https://good-origin.com",
},
});
request(srv)
.get("/socket.io/socket.io.js")
.set("origin", "https://good-origin.com")
.buffer(true)
.end((err, res) => {
if (err) return done(err);
expect(res.headers["access-control-allow-origin"]).to.be(
"https://good-origin.com"
);
expect(res.status).to.be(200);
done();
});
});
it(
"should serve bundle with msgpack parser",
testSource("socket.io.msgpack.min.js")

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 });
@@ -852,10 +869,6 @@ describe("socket", () => {
it("should not crash when messing with Object prototype (and other globals)", (done) => {
// @ts-ignore
Object.prototype.foo = "bar";
// @ts-ignore
global.File = "";
// @ts-ignore
global.Blob = [];
const io = new Server(0);
const socket = createClient(io);