Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: socketio/socket.io
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2f6cc2fa4287de02fa5c9b8f5bf7d5beb37acf2f
Choose a base ref
...
head repository: socketio/socket.io
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c332643ad8b2eff3a9edee432bfd53fb37559280
Choose a head ref
  • 6 commits
  • 21 files changed
  • 2 contributors

Commits on Jun 29, 2023

  1. Copy the full SHA
    443e447 View commit details

Commits on Jul 9, 2023

  1. 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: socketio/engine.io#686
    
    [1]: socketio/engine.io@37474c7
    darrachequesne committed Jul 9, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    03046a6 View commit details

Commits on Jul 21, 2023

  1. Copy the full SHA
    0731c0d View commit details

Commits on Aug 2, 2023

  1. Copy the full SHA
    09d4549 View commit details
  2. fix(webtransport): properly handle WebTransport-only connections

    A WebTransport-only connection has no `request` attribute, so we need
    to handle that case.
    darrachequesne committed Aug 2, 2023
    Copy the full SHA
    3468a19 View commit details
  3. chore(release): 4.7.2

    darrachequesne committed Aug 2, 2023
    Copy the full SHA
    c332643 View commit details
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 2 additions & 2 deletions client-dist/socket.io.esm.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client-dist/socket.io.esm.min.js.map

Large diffs are not rendered by default.

174 changes: 137 additions & 37 deletions client-dist/socket.io.js
2 changes: 1 addition & 1 deletion client-dist/socket.io.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions client-dist/socket.io.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client-dist/socket.io.min.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions client-dist/socket.io.msgpack.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client-dist/socket.io.msgpack.min.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions examples/webtransport/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pem
18 changes: 18 additions & 0 deletions examples/webtransport/README.md
Original file line number Diff line number Diff line change
@@ -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
```
8 changes: 8 additions & 0 deletions examples/webtransport/generate_cert.sh
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions examples/webtransport/index.html
Original file line number Diff line number Diff line change
@@ -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>
68 changes: 68 additions & 0 deletions examples/webtransport/index.js
Original file line number Diff line number Diff line change
@@ -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();
10 changes: 10 additions & 0 deletions examples/webtransport/open_chrome.sh
Original file line number Diff line number Diff line change
@@ -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
11 changes: 11 additions & 0 deletions examples/webtransport/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
12 changes: 6 additions & 6 deletions lib/socket.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 36 additions & 36 deletions package-lock.json
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -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"
70 changes: 70 additions & 0 deletions test/namespaces.ts
Original file line number Diff line number Diff line change
@@ -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+$/);
17 changes: 17 additions & 0 deletions test/socket.ts
Original file line number Diff line number Diff line change
@@ -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 });