Skip to content

Commit

Permalink
docs(examples): add example with express-session
Browse files Browse the repository at this point in the history
Related: #3933
  • Loading branch information
darrachequesne committed Apr 2, 2022
1 parent 9f75868 commit d12aab2
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 0 deletions.
16 changes: 16 additions & 0 deletions examples/express-session-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Example with [express-session](https://www.npmjs.com/package/express-session)

This example shows how to share a session context between [Express](http://expressjs.com/) and [Socket.IO](https://socket.io/docs/v4/):

![Video of the example](assets/demo.gif)

Please read the related guide: https://socket.io/how-to/use-with-express-session

## How to use

```
$ npm install
$ npm start
```

And point your browser to `http://localhost:3000`. Optionally, specify a port by supplying the `PORT` env variable.
Binary file added examples/express-session-example/assets/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions examples/express-session-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Example with express-session</title>
</head>
<body>
<button onclick="incrementWithFetch()">Increment with fetch()</button>
<button onclick="logout()">Logout</button>
<p>Count: <span id="httpCount">0</span></p>

<button onclick="incrementWithEmit()">
Increment with Socket.IO emit()
</button>
<p>Status: <span id="ioStatus">disconnected</span></p>
<p>Count: <span id="ioCount">0</span></p>

<script src="/socket.io/socket.io.js"></script>
<script>
const httpCount = document.getElementById("httpCount");
const ioStatus = document.getElementById("ioStatus");
const ioCount = document.getElementById("ioCount");

const socket = io({
// with WebSocket only
// transports: ["websocket"],
});

async function incrementWithFetch() {
const response = await fetch("/incr", {
method: "post",
});
httpCount.innerText = await response.text();
}

function logout() {
fetch("/logout", {
method: "post",
});
}

async function incrementWithEmit() {
socket.emit("incr", (count) => {
ioCount.innerText = count;
});
}

socket.on("connect", () => {
ioStatus.innerText = "connected";
});

socket.on("disconnect", () => {
ioStatus.innerText = "disconnected";
});
</script>
</body>
</html>
91 changes: 91 additions & 0 deletions examples/express-session-example/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import express from "express";
import { createServer } from "http";
import { Server } from "socket.io";
import session from "express-session";

const port = process.env.PORT || 3000;

const app = express();
const httpServer = createServer(app);

const sessionMiddleware = session({
secret: "changeit",
resave: true,
saveUninitialized: true,
});

app.use(sessionMiddleware);

app.get("/", (req, res) => {
res.sendFile("./index.html", { root: process.cwd() });
});

app.post("/incr", (req, res) => {
const session = req.session;
session.count = (session.count || 0) + 1;
res.status(200).end("" + session.count);
});

app.post("/logout", (req, res) => {
const sessionId = req.session.id;
req.session.destroy(() => {
// disconnect all Socket.IO connections linked to this session ID
io.to(sessionId).disconnectSockets();
res.status(204).end();
});
});

const io = new Server(httpServer, {
allowRequest: (req, callback) => {
// with HTTP long-polling, we have access to the HTTP response here, but this is not
// the case with WebSocket, so we provide a dummy response object
const fakeRes = {
getHeader() {
return [];
},
setHeader(key, values) {
req.cookieHolder = values[0];
},
writeHead() {},
};
sessionMiddleware(req, fakeRes, () => {
if (req.session) {
// trigger the setHeader() above
fakeRes.writeHead();
// manually save the session (normally triggered by res.end())
req.session.save();
}
callback(null, true);
});
},
});

io.engine.on("initial_headers", (headers, req) => {
if (req.cookieHolder) {
headers["set-cookie"] = req.cookieHolder;
delete req.cookieHolder;
}
});

io.on("connect", (socket) => {
const req = socket.request;

socket.join(req.session.id);

socket.on("incr", (cb) => {
req.session.reload((err) => {
if (err) {
// session has expired
return socket.disconnect();
}
req.session.count = (req.session.count || 0) + 1;
req.session.save(() => {
cb(req.session.count);
});
});
});
});

httpServer.listen(port, () => {
console.log(`application is running at: http://localhost:${port}`);
});
15 changes: 15 additions & 0 deletions examples/express-session-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "express-session-example",
"version": "0.0.1",
"private": true,
"type": "module",
"description": "Example with express-session (https://github.com/expressjs/session)",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "~4.17.3",
"express-session": "~1.17.2",
"socket.io": "~4.4.1"
}
}

0 comments on commit d12aab2

Please sign in to comment.