使用express中间件时结合sockets和express?

Posted

技术标签:

【中文标题】使用express中间件时结合sockets和express?【英文标题】:Combine sockets and express when using express middleware? 【发布时间】:2017-07-11 19:42:43 【问题描述】:

有没有办法在快速中间件中获取请求的套接字?

即:

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!')
)

这个想法是 express 中间件有一个 req.socket 属性,它引用来自同一客户端的连接套接字。这将允许一些更复杂的用例,例如:

app.post('/image/create', (req, res) => 
  createExpensiveImage(
    onProgress: (progress) =>  req.socket.emit('image:progress',  progress ) ,
  );
)

客户端将获得他们刚刚请求通过 API 创建的图像的准确进度条。

【问题讨论】:

也许这个How to share sessions between socket.io and express。仅供参考,当您在 Google 上搜索“share session express socket.io”时,会有数百次点击。很多关于这个的文章。 【参考方案1】:

这里有一种连接socket.io和express的方法。它使用 express-session 为给定的客户端创建一个安全的会话对象。然后,当 socket.io 连接发生时,它会获取该客户端的会话并将 socket.id 存储在会话中。

然后,您可以从快速路由处理程序中的会话中获取 socketID,以便您可以通过 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");
);

【讨论】:

很好,谢谢。我以前见过 express 和 sockets 之间的会话共享,但从未想过以这种方式使用它。事后看来似乎很简单。 由于某些原因,req.session 没有适合我的 socketio。会话中只有一个cookie。

以上是关于使用express中间件时结合sockets和express?的主要内容,如果未能解决你的问题,请参考以下文章

如何结合 Express.JS 使用 Socket.io(使用 Express 应用程序生成器)

使用 Express.js v4 和 Socket.io v1 的会话

如何在用户从帐户注销时断开事件触发(node.js + express socket.io)

express js 中的 Socket.io:Router.use 需要中间件功能但未定义

AngularJS 不使用 socket.io 刷新视图

与 socket.io 一起使用时 express-session 未设置会话 cookie