WebSocket 握手期间的 WebSockets WS 错误:意外的响应代码:200
WebSockets WS error during WebSocket handshake: Unexpected response code: 200
尝试在 Heroku 上使用 ws 部署我的应用程序。在我的本地机器上一切正常,但在 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);
//
});
ws Server
constructor 不接受 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 规范的响应并正确地抛出错误。它报告 "status 200" 因为服务器 确实 响应了 HTTP 200 状态代码 — 即使这是一个意外。
将 ws Server
附加到 HTTP 服务器的正确方法是:
将http.Server
(不是快递应用)传递给ws.Server
的server
选项
var app = express(),
server = http.createServer(app),
wss = new ws.Server({ server });
server.listen(process.env.PORT);
或手动附加一个upgrade
listener to your http.Server
and call wss.handleUpgrade
.
尝试在 Heroku 上使用 ws 部署我的应用程序。在我的本地机器上一切正常,但在 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);
//
});
ws Server
constructor 不接受 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 规范的响应并正确地抛出错误。它报告 "status 200" 因为服务器 确实 响应了 HTTP 200 状态代码 — 即使这是一个意外。
将 ws Server
附加到 HTTP 服务器的正确方法是:
将
http.Server
(不是快递应用)传递给ws.Server
的server
选项var app = express(), server = http.createServer(app), wss = new ws.Server({ server }); server.listen(process.env.PORT);
或手动附加一个
upgrade
listener to yourhttp.Server
and callwss.handleUpgrade
.