You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级WebSocket连接时如何获取Express风格的request请求对象

解决思路很简单:upgrade事件拿到的原生request没有经过Express中间件处理,你只需要在处理WebSocket升级前,手动让这个原生request执行一遍你需要的Express中间件,等用户信息挂载完成后再走升级逻辑即可。

具体实现步骤

  1. 提前抽离需要用到的、会向request挂载用户信息的中间件(比如会话中间件、权限校验中间件等),同时保持原来的Express注册逻辑不变:
// 示例为session + passport鉴权的场景,可替换为你自己的业务中间件
const sessionMiddleware = session({
  secret: "自定义会话密钥",
  resave: false,
  saveUninitialized: false,
  cookie: { secure: process.env.NODE_ENV === "production" }
})
const passportInit = passport.initialize()
const passportSession = passport.session()

// 原有Express注册中间件的逻辑不变
app.use(sessionMiddleware)
app.use(passportInit)
app.use(passportSession)
  1. 修改upgrade事件逻辑,在执行handleUpgrade前先运行上述中间件处理原生request,校验通过后再完成升级,同时可以直接把用户信息挂载到ws实例上方便后续使用:
server.on('upgrade', (request, socket: any, head) => {
  // 按顺序执行需要的中间件,第二个参数传空对象占位response即可
  sessionMiddleware(request, {} as any, () => {
    passportInit(request, {} as any, () => {
      passportSession(request, {} as any, () => {
        // 此时request上已经挂载了用户信息,可做权限校验
        if (!request.user) {
          // 无权限直接拒绝连接
          socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n')
          socket.destroy()
          return
        }
        wss.handleUpgrade(request, socket, head, (ws: WebSocket) => {
          // 将用户信息挂载到ws实例,后续收发消息时可直接读取
          ws.user = request.user
          wss.emit('connection', ws, request)
        })
      })
    })
  })
})

如果你用的是自定义的鉴权中间件,直接替换上面的session、passport相关中间件即可,逻辑完全一致。


优化方案(避免回调嵌套)

可以把中间件执行封装成Promise,用async/await简化代码:

// 封装中间件执行函数
function runMiddleware(req: any, res: any, middleware: Function) {
  return new Promise((resolve, reject) => {
    middleware(req, res, (result: any) => {
      if (result instanceof Error) return reject(result)
      resolve(result)
    })
  })
}

// 改造后的upgrade逻辑
server.on('upgrade', async (request, socket: any, head) => {
  try {
    const emptyRes = {} as any
    await runMiddleware(request, emptyRes, sessionMiddleware)
    await runMiddleware(request, emptyRes, passportInit)
    await runMiddleware(request, emptyRes, passportSession)

    if (!request.user) {
      socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n')
      socket.destroy()
      return
    }

    wss.handleUpgrade(request, socket, head, (ws: WebSocket) => {
      ws.user = request.user
      wss.emit('connection', ws, request)
    })
  } catch (err) {
    socket.write('HTTP/1.1 500 Internal Server Error\r\n\r\n')
    socket.destroy()
  }
})

内容的提问来源于stack exchange,提问作者jdoe8227

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 16:15:08