有没有办法在快速中间件内获取请求的套接字?
即:
import express from 'express';
import io from 'socket.io';
const app = express();
// combine app and io somehow ...
// When client makes a GET request to '/emit/to/self', that client's socket will recieve the 'hello:world' message.
app.get('/emit/to/self', (req, res) => {
req.socket.emit('hello:world', { ... });
res.send('You just triggered your own socket!')
})
这个想法是,快速中间件有一个
req.socket
属性,它引用来自同一客户端的已连接套接字。这将允许一些更复杂的用例,例如:
app.post('/image/create', (req, res) => {
createExpensiveImage({
onProgress: (progress) => { req.socket.emit('image:progress', { progress }) },
});
})
客户将拥有他们刚刚通过 API 请求创建的图像的准确进度条。
这里介绍一种连接socket.io和express的方法。它使用 Express-Session 为给定客户端创建安全会话对象。然后,当发生 socket.io 连接时,它会获取该客户端的会话并将 socket.id 存储在会话中。
然后,您可以从快速路由处理程序中的会话中获取套接字ID,以便您可以通过socket.io 向该客户端发送。或者,当您位于 socket.io 消息处理程序中时,您可以从该用户获取会话数据。你可以选择任何一种方式。这是基本代码:
const express = require('express');
const app = express();
const server = app.listen(80);
const io = require('socket.io')(server);
const expsession = require('express-session');
const path = require('path');
// initialize session middleware
const sessionMiddleware = expsession({
secret: 'random secret',
saveUninitialized: true,
resave: true
});
// hook up session for express routes
app.use(sessionMiddleware);
// hook up the session for socket.io connections
io.use(function(socket, next) {
sessionMiddleware(socket.request, socket.request.res, next);
});
// when a socket.io connect connects, get the session and store the id in it
io.on('connection', function(socket) {
// socket.handshake.headers
console.log(`socket.io connected: ${socket.id}`);
// save socket.io socket in the session
console.log("session at socket.io connection:\n", socket.request.session);
socket.request.session.socketio = socket.id;
socket.request.session.save();
});
// general middleware to demo an increasing, per-client value in the session
app.use(function(req, res, next) {
// req.session
const session = req.session;
if (!session.cntr) session.cntr = 0;
++session.cntr;
next();
});
// route handler to serve up default page
app.get("/", function(req, res) {
const session = req.session;
console.log("\n\npage load\n---------------------------\n");
console.log("session:\n", session);
res.sendFile(path.join(__dirname, "socket-io-session.html"));
});
let cntr = 1;
// test route to show using socket.io .emit() from an express route
app.get("/api/test", function(req, res) {
const session = req.session;
io.sockets.connected[session.socketio].emit('show', cntr++);
res.json({greeting: "hello"});
});
最后,套接字版本 4.6.0 可以实现
这里是基本示例:
import session from "express-session";
io.engine.use(session({
secret: "keyboard cat",
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
Socket.io 官方文档:https://socket.io/docs/v4/middlewares/#compatibility-with-express-middleware