NextJS, Express, Ошибка во время рукопожатия WebSocket: Неожиданный код ответа: 200 - PullRequest
1 голос
/ 23 сентября 2019

Основная проблема может быть кратко изложена следующим образом: при создании сервера Websocket в Node с использованием ws с параметром сервера, заполненным сервером экспресс-обслуживания (как в в этом примере), в то время какиспользуя тот же самый экспресс-сервер для обработки маршрутизации для NextJS (как в этом примере), заголовок обновления, кажется, не анализируется должным образом.

Вместо того, чтобы запрос перенаправлялся на сервер Websocket, экспресс отправляет ответ HTTP 200 OK.

Я искал ответ на этот вопрос, возможно, япросто не понимаю проблемы.Возможно связанный вопрос был поднят в выпуске на github NextJS.Они рекомендуют устанавливать параметры WebsocketPort и WebsocketProxyPort в локальном файле next.config.js, однако я попытался это сделать безрезультатно.

Ниже приведен минимальный пример соответствующего кода сервера.Вы можете найти полный пример здесь .

const express = require('express')
const next = require('next')
const SocketServer = require('ws').Server;
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
    const server = express()

    server.all('*', (req, res) => {
    return handle(req, res)
    })

    server.listen(port, err => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
    })

    const wss = new SocketServer({ server });

    wss.on('connection', function connection(ws, request) {
        console.log('Client connected');
        ws.on('close', () => console.log('Client disconnected'));
    });
    wss.on('error', function (error) {
        console.log(error);
    });

    setInterval(() => {
        wss.clients.forEach((client) => {
          client.send(new Date().toTimeString());
        });
      }, 1000);    

}).catch(ex => {
    console.error(ex.stack);
    process.exit(1);
});

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

WebSocket connection to 'ws://localhost:3000/' failed: Error during WebSocket handshake: Unexpected response code: 200

Может кто-нибудь объяснить мне что-нибудь здесь?

1 Ответ

0 голосов
/ 23 сентября 2019

Хорошо, после еще копания я решил проблему.Проще говоря, объект ws.Server, которому я пытался передать объект server = express(), строго говоря, не является объектом http-сервера.Однако server.listen() возвращает такой объект http-сервера.На таком объекте мы можем прослушивать вызов 'upgrade', который мы можем передать нашему ws.Server прослушивателю событий handleUpgrade() объекта, через который мы можем подключиться.Я буду обновлять примеры, которые я связал в своем вопросе, но соответствующий код приведен ниже:

app.prepare().then(() => {
    const server = express()

    server.all('*', (req, res) => {
    return handle(req, res)
    })

    const wss = new SocketServer({ server });

    wss.on('connection', function connection(ws, request) {
        console.log('Client connected');
        ws.on('close', () => console.log('Client disconnected'));
    });
    wss.on('error', function (error) {
        console.log(error);
    });

    let srv = server.listen(port, err => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
    })

    srv.on('upgrade', function(req, socket, head) {
        wss.handleUpgrade(req, socket, head, function connected(ws) {
            wss.emit('connection', ws, req);
        })
    });

...