Socket.io «Недопустимый заголовок фрейма» с независимым сервером веб-сокетов - PullRequest
0 голосов
/ 07 ноября 2018

Есть ли способ заставить отдельный сервер веб-сокетов работать вместе с 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'));

Поведение, которое я вижу, заключается в том, что при создании отдельного сервера веб-сокетов socket.io по-прежнему функционирует должным образом, но не обновляет подключения к веб-сокету и завершается с ошибкой (из 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, когда подписки включены. Есть ли способ настроить socket.io более удобным способом? Или я полагаю, что могу предоставить сервер веб-сокетов для использования Apollo вместо его создания ... как бы я это создал?

Варианты комплекта для воспроизведения:

node       8.11.1
express    4.16.4
socket.io  2.1.1
ws         6.1.0

1 Ответ

0 голосов
/ 07 ноября 2018

Если это кому-нибудь еще поможет, вот мое производное решение:

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();
});

Это немного раздражало, потому что обе библиотеки уже полностью инициализировали свои серверы веб-сокетов с большим количеством прослушивателей событий, прежде чем я мог связываться с ними. Тем не менее, я мог бы выбрать 'upgrade' слушателей и передать их вручную. Конечно, это не идеально, так как он чувствителен к порядку инициализации и новым слушателям, но этого достаточно для моего варианта использования.

Если в этом решении есть какие-то явные недостатки или какие-либо другие нюансы с делегированием сервера websocket, пожалуйста, сообщите мне.

...