node.jsexpresswebsocketws

Error connecting to websockets NodeJS Express server


I have an express server with websockets configured:

/tmp/ws-test $ cat httpServer.js
const express = require('express');
const WebSocket = require('ws');

const app = express();
const port = 8080;

app.get('/', function(req, res, next) {
  return res.send('Hello World!');
});

const wss = new WebSocket.Server({ server: app });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: %s', message);
  });
  ws.send('something from server');
});

app.listen(port, function(err) {
  if (err) {
    throw err;
  }
  console.log(`listening on port ${port}!`);
});

It runs as expected:

/tmp/ws-test $ node httpServer.js
listening on port 8080!

I have a client:

/tmp/ws-test $ cat client.js
const WebSocket = require('ws');

const ws = new WebSocket('ws://localhost:8080');

ws.on('open', function open() {
  ws.send('something from client');
});

ws.on('message', function incoming(data) {
  console.log(`received: ${data}`);
});

It errors:

/tmp/ws-test $ node client.js
events.js:180
      throw er; // Unhandled 'error' event
      ^

Error: Unexpected server response: 200
    at ClientRequest.<anonymous> (/private/tmp/ws-test/node_modules/ws/lib/websocket.js:579:7)
    at ClientRequest.emit (events.js:203:13)
    at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:575:27)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:116:17)
    at Socket.socketOnData (_http_client.js:449:22)
    at Socket.emit (events.js:203:13)
    at addChunk (_stream_readable.js:295:12)
    at readableAddChunk (_stream_readable.js:276:11)
    at Socket.Readable.push (_stream_readable.js:210:10)
    at TCP.onStreamRead (internal/stream_base_commons.js:166:17)
Emitted 'error' event at:
    at abortHandshake (/private/tmp/ws-test/node_modules/ws/lib/websocket.js:697:15)
    at ClientRequest.<anonymous> (/private/tmp/ws-test/node_modules/ws/lib/websocket.js:579:7)
    [... lines matching original stack trace ...]
    at Socket.Readable.push (_stream_readable.js:210:10)

In the client I also tried using http for the web socket connection.

const ws = new WebSocket('http://localhost:8080');

But it throws the same error.

Why is the client erroring on connection to the server?


Solution

  • You should pass an http server instance to WebSocket.Server constructor instead of an instance of express application:

    const express = require('express');
    const WebSocket = require('ws');
    const http = require('http');
    
    const app = express();
    const port = 8080;
    
    const server = http.createServer(app);
    
    app.get('/', function(req, res, next) {
        return res.send('Hello World!');
    });
    
    const wss = new WebSocket.Server({ server });
    
    wss.on('connection', function connection(ws) {
        ws.on('message', function incoming(message) {
            console.log('received: %s', message);
        });
        ws.send('something from server');
    });
    
    server.listen(port, function(err) {
        if (err) {
            throw err;
        }
        console.log(`listening on port ${port}!`);
    });