有没有办法让单独的websocket服务器与socket.io
在不同的路径上一起工作?
let http = require('http');
let express = require('express');
let socketio = require('socket.io');
let websocket = require('ws');
let httpServer = http.createServer();
let expressApp = express();
httpServer.on('request', expressApp);
let socketioServer = socketio(httpServer, { path: '/aaaaa/socket.io/' });
socketioServer.of('/').on('connect', () => {});
let websocketServer = new websocket.Server({ server: httpServer, path: '/aaaaa/graphql' });
httpServer.listen(2233, () => console.log('started'));
我看到的行为是,当创建单独的websocket服务器时,socket.io
仍然可以正常运行,但是不会升级与websocket的连接,并且会失败并出现错误(来自chrome):
WebSocket connection to 'ws://localhost:2233/aaaaa/socket.io/?EIO=3&transport=websocket&sid=fx4pOT0cegz65JMCAAAB' failed: Invalid frame header
请注意,如果省略了websocket服务器行,则socket.io
可以正常工作。
我的特定用例是启用订阅后,由apollo-server-express
包创建Websocket服务器。有没有一种以更友好的方式配置socket.io
的方法?或者,我相信我可以提供一个供apollo使用的websocket服务器,而不是创建一个...我将如何创建它?
要复制的软件包版本:
node 8.11.1
express 4.16.4
socket.io 2.1.1
ws 6.1.0
答案 0 :(得分:1)
万一这可以帮助其他人,这是我的派生解决方案:
let [socketioUpgradeListener, apolloUpgradeListener] = httpServer.listeners('upgrade').slice(0);
httpServer.removeAllListeners('upgrade');
httpServer.on('upgrade', (req, socket, head) => {
const pathname = url.parse(req.url).pathname;
if (pathname == '/aaaaa/socket.io/')
socketioUpgradeListener(req, socket, head);
else if (pathname == '/aaaaa/graphql')
apolloUpgradeListener(req, socket, head);
else
socket.destroy();
});
有点烦人,因为两个库都已经完全初始化了它们的websocket服务器,并带有大量事件侦听器,然后我才将它们弄乱了。但是,我可以选择'upgrade'
侦听器并手动委派它们。当然,这不是完美的,因为它对初始化顺序和新的侦听器敏感,但是对于我的用例来说就足够了。
如果此解决方案存在任何明显的缺陷,或者websocket服务器委派有任何其他细微差别,请告诉我。
答案 1 :(得分:0)
同时使用NestJs
-和graphql
时,在socket.io-modules
中出现了相同的问题。作为Trevor解决方案的替代方案,您可以将socket.io
绑定到另一个端口,并使用像nginx这样的反向代理来解析路径。
app.gateway.ts
@WebSocketGateway(3001)
export class AppGateway implements OnGatewayConnection {
handleConnection(
client: any,
payload: any
) {
client.emit('Hi from port 3001');
}
}
nginx.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
location /graphql {
proxy_pass http://127.0.0.1:3000;
}
location /socket.io {
proxy_pass http://127.0.0.1:3001/socket.io/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
}
}
当然,您可以跳过最后一部分,并直接通过客户端上的ws://localhost:3001/socket.io
连接到套接字。