NextJS,Express,WebSocket握手期间错误:意外的响应代码:200

时间:2019-09-23 00:52:27

标签: javascript node.js express websocket next.js

基本问题可以总结如下:当使用ws在Node中创建Websocket服务器时,其中的服务器选项由Express服务器填充(例如this),而使用同一Express服务器处理NextJS的路由(如this示例中所示),升级标头似乎未正确解析。

express不会将请求路由到Websocket服务器,而是发送回HTTP 200 OK响应。

我一直在寻找答案,可能是我根本不了解问题。 NextJS的github上的issue中提出了一个可能相关的问题。他们建议在本地的next.config.js中设置WebsocketPort和WebsocketProxyPort选项,但是我尝试这样做没有任何作用。

有关服务器代码的最小示例可以在下面找到。您可能会找到完整的示例here

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服务器的连接。相反,我收到以下错误:

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

有人可以在这里为我澄清任何事情吗?

1 个答案:

答案 0 :(得分:0)

好吧,经过更多的挖掘,我解决了这个问题。很简单,我试图向其提供ws.Server对象的server = express()对象并不是严格意义上的http服务器对象。但是,server.listen()返回这样的http服务器对象。在这样的对象上,我们可以侦听“升级”调用,然后将其传递给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);
        })
    });