在 NodeJs Express 中让 SocketIO 在 HTTPS 上工作

问题描述 投票:0回答:1

大家好

将我的 NodedJs 应用程序推送到我的 ubuntu 服务器(使用 https 在 nginx 中提供站点)后,我遇到了问题。在我使用 localhost 的本地环境中,连接已成功建立,但是在推送到服务器后,我在客户端 JavaScript 控制台内的第二个应用程序(管理员)admin.domainname.com 中收到以下响应:

manager.js:108 WebSocket connection to 'wss://domainname.com/socket.io/?EIO=4&transport=websocket' failed

这是我在domainname.com上运行的第一个应用程序中建立套接字并发送消息的部分:

/*rest of app.js file with express.js*/ 

const PORT = 3000;

const server = app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`)
})

const socket = socketIo(server);

socket.on('connection', (socket) => {
    console.log("connected")
    socket.emit("testmessage", "Hello World")
    socket.on('disconnect', () => {});
});

在我的客户端 JavaScript 内的第二个应用程序 (admin.domainname.com) 中,我想接收如下消息:

const socketdomainconstruct = () => {
    if (location.port) {
      return "http://localhost:3000"
    } else {
      return "https://domainname.com"
    }
  }
  
const socket = io(socketdomainconstruct(), { transports: ['websocket', 'polling', 'flashsocket'] 

socket.on("connect", () => {
  console.log("connected");
  socket.on("testmessage", (message) => {
    console.log(message);
  });
});

为了解释,当我在上面的 socket.io 实例中使用 http://localhost:3000 时,我可以成功连接并且一切都按预期工作,因此整体结构没有问题。只有当我切换到 https 时,我才会收到错误,我似乎不明白,因为没有任何改变。

潜在问题可能在于:

  • 我初始化Socket服务器的方式(也许无法通过https访问它,但这会很奇怪,因为nodejs应用程序是在带有有效ssl证书的nginx内运行的,也许我还需要包含Socket的配置。 io服务器??)
  • Cors => 但我没有收到任何错误,并且我所有的标题都已设置(两个应用程序基本上都相同)=> 见下文:
app.use((req, res, next) => {

  res.removeHeader('Server');
  res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
  res.setHeader('Pragma', 'no-cache');
  res.setHeader('Expires', '0');
  res.setHeader('Last-Modified', new Date().toUTCString());
  res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.socket.io code.jquery.com cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' bing.com; connect-src 'self' *");
  res.setHeader('Permission-Policy', 'accelerometer=(), camera=(), microphone=(), geolocation=(), gyroscope=()');
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'deny');
  res.setHeader('X-XSS-Protection', '1; mode=block');
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
  next();
  
});

我希望有人可以帮助我澄清/隔离问题,甚至与我一起解决它,作为参考,我还将包含来自 Socket.io 的有用链接

预先感谢您提供的任何帮助和提示,这对我来说真的很有帮助!

干杯拉斐尔

node.js express sockets websocket socket.io
1个回答
0
投票

问题已解决,首先将正确的 cors 选项添加到 SocketIO 服务器对象:

socketIo(服务器, {cors: {origin: ["https://admin.domainname.com", "http://localhost:3000"]}}); // 数组风格的写法可以包含多个原点...

请参阅有关 SocketIO 的文档了解更多信息:

我还必须正确设置 Nginx 代理,如下所示:

location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;

        proxy_pass http://admin-container:4000; #localhost in case of not running the app inside a Docker container

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade; #important part for Websocket connection to work
        proxy_set_header Connection 'upgrade'; #important part for Websocket connection to work
        proxy_cache_bypass $http_upgrade;
   }

这也可以在 SocketIO 文档中看到,它不仅适用于 Nginx,还适用于 Apache 和 Caddy2!

总的来说,这个问题可以通过正确阅读文档来避免,它们非常好,感谢大家的帮助,祝你有美好的一天,希望问题的解决可以帮助其他有类似问题的人

我的设置是

  • Node V.18 lts 在 Docker 容器中运行的应用程序
  • Nginx
  • Ubuntu

干杯拉斐尔

© www.soinside.com 2019 - 2024. All rights reserved.