+-
在WebSocket握手期间,WebSocket WS错误。意外的响应代码。200

试图用ws在Heroku上部署我的应用程序。在我的本地机器上,一切都很顺利,但在Heroku上部署后,我得到一个响应状态为200的握手错误。

这是我的服务器代码。

const WebSocketServer = require('ws').Server;
const moment = require('moment');
const app = require('./app');

const wss = new WebSocketServer({ app });

const connections = new Set();

wss.on('connection', (ws) => {
  connections.add(ws);

  ws.on('message', (message) => {
    const time = moment(new Date()).format('HH:mm');
    const messageData = {
      time,
      message,
    };
    for (const connection of connections) {
      connection.send(JSON.stringify(messageData));
    }
  });

  ws.on('close', () => {
    connections.delete(ws);
  });
 });

还有我的客户端代码

const HOST = location.origin.replace(/^http/, 'ws');
const ws = new WebSocket(HOST);

ws.onmessage = (e) => {
  //
};

messageForm.addEventListener('submit', (e) => {
  //
  ws.send(message);
  //
});
1
投票

该 ws Server 构造者 不接受 app 选项,所以你的 wss 实际上并没有监听到任何东西。 如果这段代码确实在本地工作,那就很难看出是怎么回事了。

由于您试图连接到与您的页面共享同一路径的 WebSocket,Express 应用程序最终会处理 WebSocket 客户端请求,并以您的页面 HTML 做出响应。

您的 HTTP 交换最终看起来像这样 - 首先,浏览器加载页面。

GET /page HTTP/1.1
Accept: text/html
…

HTTP/1.1 200 OK
Content-Type: text/html

<html> …

然后页面进行一个 new WebSocket(…),导致 WebSocket 升级请求。

GET /page HTTP/1.1
Connection: Upgrade
Upgrade: websocket
…

HTTP/1.1 200 OK
Content-Type: text/html

<html> …

你应该知道为什么会失败:这不是一个WebSocket响应。 Express认为该请求是一个普通的HTTP GET 请求,并使用您的页面的 HTML 进行响应。 浏览器的 WebSocket 实现看到不符合 WebSocket 规范的响应,并正确地抛出一个错误。 它报告 "状态 200",因为服务器 做了 响应一个HTTP 200状态码--尽管这是一个意外。

连接ws的正确方法是 Server 到HTTP服务器是以任一。

传入 http.Server ( 快递应用)到 ws.Server's server 选择权

var app = express(),
    server = http.createServer(app),
    wss = new ws.Server({ server });

server.listen(process.env.PORT);

或手动附加一个 upgrade 倾听者 http.Server 并称 wss.handleUpgrade.