我正在使用快递和HPM代理所有请求到我的网站。所有这些都封装在一个我称之为ws-proxy的小工具中( web服务器的ws,而不是websocket)。
代理的内容之一是我的PVE/节点,它将安全WebSockets用于xterm.js和NoVNC控制台。
奇怪的是,在启动ws-代理之后,我有大约30秒的时间打开一个将持续的控制台,但是连接在这段时间后将关闭,出现404未找到的错误。在控制台,我看到了
[HPM] Upgrading to WebSocket
[HPM] Upgrading to WebSocket (sometimes up to 4 times)
[HPM] Client disconnected在我的浏览器中,我看到返回的连接为404。
对于websocat,我得到:
websocat: WebSocketError: Received unexpected status code (404 Not Found)
websocat: error running经过额外的调试后,我在堆栈中看到了一些东西:发送404并关闭连接,然后PVE发送101交换协议。这有时还会导致结束后写错误,有时套接字挂起。
我花了几个月的时间研究这个问题,现在我没有别的地方可以看了。
404在视察元素中:

最近一次尝试后控制台中的错误日志(错误将更改)

客户端和服务器之间步骤的完整列表:
非websocket (HTTP)请求可以正常工作。这是与HPM v2和Node.js v16。
在Ryker的回答之后,更新1,我尝试了应该修复它的解决方案,但是在将logLevel设置为调试之后,我看到了其他一些值得关注的问题:
0|ws-proxy | pve.internal.0xlogn.dev ::1 - - [02/Nov/2022:23:17:14 +0000] "POST /api2/json/nodes/proxmox/lxc/105/termproxy HTTP/1.1" 200 487 "https://pve.internal.0xlogn.dev/?console=lxc&vmid=105&node=proxmox&resize=scale&xtermjs=1" "Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0"
0|ws-proxy | Upgrade request for vhost pve.internal.0xlogn.dev, proxy out
0|ws-proxy | [HPM] GET /api2/json/nodes/proxmox/lxc/105/vncwebsocket?port=5900&vncticket=REDACTED -> https://10.0.1.2:8006
0|ws-proxy | [HPM] GET /api2/json/nodes/proxmox/lxc/105/vncwebsocket?port=5900&vncticket=REDACTED -> http://10.0.1.108:80
0|ws-proxy | [HPM] Upgrading to WebSocket
0|ws-proxy | [HPM] Upgrading to WebSocket
0|ws-proxy | [HPM] Client disconnected
0|ws-proxy | [HPM] GET /api2/json/cluster/resources -> https://10.0.1.2:8006注意到这两个请求了吗?有些东西在重复请求。
我的'upgrade'事件侦听器:
httpsServer.on('upgrade', (req, socket, head) => {
if (!req.headers.host) {
console.log('No vhost specified in upgrade request. Ignoring.');
socket.end();
return;
} else {
console.log(`Upgrade request for vhost ${req.headers.host}, proxy out`);
vhostProxyMiddlewareList[req.headers.host].upgrade(req, socket, head);
}
})更奇怪的是,在重新启动之后,我得到了一个不重复请求的短时间。另外,还有一个正常的HTTP请求。
更新2在注意到双重请求之后,我相信模块vhost可能会导致奇怪的通配符,并将请求发送到两个目标节点。我很快就会有最新消息。
更新3经过进一步的工作,我相信这是正确的。但是,vhost不是错误,而是隐式调用next()。
发布于 2022-11-04 03:41:56
这完全是我的错。
所有这些似乎都不是由快递或HPM造成的。我相信Express意味着当中间件返回一个真实值时,它希望调用next()。基本上,这是因为HPM返回了一些真实的东西,然后快递将请求传递到了更深的链上,最终击中了另一个非websocket服务器。
代码更改就像以这种方式更改函数defineNewVHost()一样简单:
function defineNewVHost(vhostURL, targetURL, addlProxyOptions) {
let vhostApp = express();
// vhostApp.use('**', createProxyMiddleware({ target: targetURL, onError, ...PROXY_DEFAULT_OPTIONS, ...addlProxyOptions }));
const proxyMw = createProxyMiddleware({ target: targetURL, onError, ...PROXY_DEFAULT_OPTIONS, ...addlProxyOptions }));
vhostApp.use('**', () => { proxyMw(); }); // NOT () => proxyMw, otherwise it'll just return that value
app.use(vhostMiddleware(vhostURL, vhostApp));
}发布于 2022-11-02 02:47:08
http代理中间件依赖于初始的http请求来默认侦听http升级事件。要在没有初始http请求的情况下代理WebSockets,可以手动订阅服务器的http升级事件。
将此侦听器添加到您的http服务器
const wsProxy = createProxyMiddleware({ target: targetURL, onError, ...PROXY_DEFAULT_OPTIONS, ...addlProxyOptions });
httpsServer.on('upgrade', wsProxy.upgrade); // <-- subscribe to http 'upgrade'https://stackoverflow.com/questions/74256645
复制相似问题