Skip to content

Commit d12aab2

Browse files
docs(examples): add example with express-session
Related: #3933
1 parent 9f75868 commit d12aab2

File tree

5 files changed

+179
-0
lines changed

5 files changed

+179
-0
lines changed
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Example with [express-session](https://www.npmjs.com/package/express-session)
2+
3+
This example shows how to share a session context between [Express](http://expressjs.com/) and [Socket.IO](https://socket.io/docs/v4/):
4+
5+
![Video of the example](assets/demo.gif)
6+
7+
Please read the related guide: https://socket.io/how-to/use-with-express-session
8+
9+
## How to use
10+
11+
```
12+
$ npm install
13+
$ npm start
14+
```
15+
16+
And point your browser to `http://localhost:3000`. Optionally, specify a port by supplying the `PORT` env variable.
80.6 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Example with express-session</title>
6+
</head>
7+
<body>
8+
<button onclick="incrementWithFetch()">Increment with fetch()</button>
9+
<button onclick="logout()">Logout</button>
10+
<p>Count: <span id="httpCount">0</span></p>
11+
12+
<button onclick="incrementWithEmit()">
13+
Increment with Socket.IO emit()
14+
</button>
15+
<p>Status: <span id="ioStatus">disconnected</span></p>
16+
<p>Count: <span id="ioCount">0</span></p>
17+
18+
<script src="/socket.io/socket.io.js"></script>
19+
<script>
20+
const httpCount = document.getElementById("httpCount");
21+
const ioStatus = document.getElementById("ioStatus");
22+
const ioCount = document.getElementById("ioCount");
23+
24+
const socket = io({
25+
// with WebSocket only
26+
// transports: ["websocket"],
27+
});
28+
29+
async function incrementWithFetch() {
30+
const response = await fetch("/incr", {
31+
method: "post",
32+
});
33+
httpCount.innerText = await response.text();
34+
}
35+
36+
function logout() {
37+
fetch("/logout", {
38+
method: "post",
39+
});
40+
}
41+
42+
async function incrementWithEmit() {
43+
socket.emit("incr", (count) => {
44+
ioCount.innerText = count;
45+
});
46+
}
47+
48+
socket.on("connect", () => {
49+
ioStatus.innerText = "connected";
50+
});
51+
52+
socket.on("disconnect", () => {
53+
ioStatus.innerText = "disconnected";
54+
});
55+
</script>
56+
</body>
57+
</html>
+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import express from "express";
2+
import { createServer } from "http";
3+
import { Server } from "socket.io";
4+
import session from "express-session";
5+
6+
const port = process.env.PORT || 3000;
7+
8+
const app = express();
9+
const httpServer = createServer(app);
10+
11+
const sessionMiddleware = session({
12+
secret: "changeit",
13+
resave: true,
14+
saveUninitialized: true,
15+
});
16+
17+
app.use(sessionMiddleware);
18+
19+
app.get("/", (req, res) => {
20+
res.sendFile("./index.html", { root: process.cwd() });
21+
});
22+
23+
app.post("/incr", (req, res) => {
24+
const session = req.session;
25+
session.count = (session.count || 0) + 1;
26+
res.status(200).end("" + session.count);
27+
});
28+
29+
app.post("/logout", (req, res) => {
30+
const sessionId = req.session.id;
31+
req.session.destroy(() => {
32+
// disconnect all Socket.IO connections linked to this session ID
33+
io.to(sessionId).disconnectSockets();
34+
res.status(204).end();
35+
});
36+
});
37+
38+
const io = new Server(httpServer, {
39+
allowRequest: (req, callback) => {
40+
// with HTTP long-polling, we have access to the HTTP response here, but this is not
41+
// the case with WebSocket, so we provide a dummy response object
42+
const fakeRes = {
43+
getHeader() {
44+
return [];
45+
},
46+
setHeader(key, values) {
47+
req.cookieHolder = values[0];
48+
},
49+
writeHead() {},
50+
};
51+
sessionMiddleware(req, fakeRes, () => {
52+
if (req.session) {
53+
// trigger the setHeader() above
54+
fakeRes.writeHead();
55+
// manually save the session (normally triggered by res.end())
56+
req.session.save();
57+
}
58+
callback(null, true);
59+
});
60+
},
61+
});
62+
63+
io.engine.on("initial_headers", (headers, req) => {
64+
if (req.cookieHolder) {
65+
headers["set-cookie"] = req.cookieHolder;
66+
delete req.cookieHolder;
67+
}
68+
});
69+
70+
io.on("connect", (socket) => {
71+
const req = socket.request;
72+
73+
socket.join(req.session.id);
74+
75+
socket.on("incr", (cb) => {
76+
req.session.reload((err) => {
77+
if (err) {
78+
// session has expired
79+
return socket.disconnect();
80+
}
81+
req.session.count = (req.session.count || 0) + 1;
82+
req.session.save(() => {
83+
cb(req.session.count);
84+
});
85+
});
86+
});
87+
});
88+
89+
httpServer.listen(port, () => {
90+
console.log(`application is running at: http://localhost:${port}`);
91+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "express-session-example",
3+
"version": "0.0.1",
4+
"private": true,
5+
"type": "module",
6+
"description": "Example with express-session (https://github.com/expressjs/session)",
7+
"scripts": {
8+
"start": "node index.js"
9+
},
10+
"dependencies": {
11+
"express": "~4.17.3",
12+
"express-session": "~1.17.2",
13+
"socket.io": "~4.4.1"
14+
}
15+
}

0 commit comments

Comments
 (0)