Is there a way to have a separate websocket server work alongside socket.io
on a different path?
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'));
The behavior I'm seeing is that, when a separate websocket server is created, socket.io
still functions properly, but will not uprade connections to a websocket and fails with the error (from chrome):
WebSocket connection to 'ws://localhost:2233/aaaaa/socket.io/?EIO=3&transport=websocket&sid=fx4pOT0cegz65JMCAAAB' failed: Invalid frame header
To be clear, if the websocket server line is omitted, socket.io
works properly.
My specific use-case is that a websocket server is created by the apollo-server-express
package when subscriptions are enabled. Is there a way to have socket.io
configured in a more friendly way? Or, I believe I can supply a websocket server for apollo to use instead of creating one... how would I create that?
Package versions for reproduction:
node 8.11.1
express 4.16.4
socket.io 2.1.1
ws 6.1.0
In case this helps anyone else, here's my derived solution:
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();
});
Was a bit annoying because both libraries had already fully initialized their websocket servers, with plenty of event listeners, before I could mess with them. However, I could pick out the 'upgrade'
listeners and delegate them manually. Of course this isn't perfect since it is sensitive to initialization order and new listeners, but it is adequate for my use-case.
If there's any glaring flaws with this solution or any other nuances with websocket server delegation, please let me know.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With