admin管理员组

文章数量:1401149

I am setting up some websockets using ws library. I am struggling to set up authorisation using a handshake. I have added a route to our server to upgrade to a websocket connection like so:

    .get(
      '/chat',
    authorisationFunction,
    upgradeConnection,
    ),

The websocket server:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3030 }); 

This is the upgradeConnection function, which will run if authorisation is successful:

const upgradeConnection = (request, socket, head) => {
  return wss.handleUpgrade(request, request.socket, head, function done(ws) {
    return wss.emit('connection', ws, request);
  });
}

I also have a function that listens to messages:

function webSocketsServer() {
  wss.on('connection', (ws, request, client) => {
    ws.on('message', message => {
      ws.send(message);
    });
  });
}

A connection gets emitted, and from my server I get this response:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: QyVvqadEcI1+ALka6j2pLKBkfNQ=

but then immediately on my client I get the error “WebSocket connection to 'ws://localhost:3000/chat’ failed: Invalid frame header”.

But when I bypass the handshake and connect directly to my websocket server, I can send messages successfully. The error is only on the client and not on the backend. What am I missing?

I am setting up some websockets using ws library. I am struggling to set up authorisation using a handshake. I have added a route to our server to upgrade to a websocket connection like so:

    .get(
      '/chat',
    authorisationFunction,
    upgradeConnection,
    ),

The websocket server:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3030 }); 

This is the upgradeConnection function, which will run if authorisation is successful:

const upgradeConnection = (request, socket, head) => {
  return wss.handleUpgrade(request, request.socket, head, function done(ws) {
    return wss.emit('connection', ws, request);
  });
}

I also have a function that listens to messages:

function webSocketsServer() {
  wss.on('connection', (ws, request, client) => {
    ws.on('message', message => {
      ws.send(message);
    });
  });
}

A connection gets emitted, and from my server I get this response:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: QyVvqadEcI1+ALka6j2pLKBkfNQ=

but then immediately on my client I get the error “WebSocket connection to 'ws://localhost:3000/chat’ failed: Invalid frame header”.

But when I bypass the handshake and connect directly to my websocket server, I can send messages successfully. The error is only on the client and not on the backend. What am I missing?

Share Improve this question edited Jun 21, 2020 at 8:14 tal asked Jun 20, 2020 at 18:50 taltal 551 gold badge1 silver badge7 bronze badges 4
  • 1 Do you maybe use a reverse proxy? Make sure it supports (and is configured to allow) websockets. For example, for Caddy you would need to specify the websocket option in the proxy block. – CherryDT Commented Jun 21, 2020 at 7:51
  • 1 Can you share the code part where you declare the websocket server? – U Rogel Commented Jun 21, 2020 at 8:08
  • @tallybee The http server is running on 3030 as well or on another port? – U Rogel Commented Jun 21, 2020 at 8:22
  • @cowCrazy http server running on 3000 – tal Commented Jun 21, 2020 at 8:25
Add a ment  | 

1 Answer 1

Reset to default 2

I am not 100% sure it is the only way but might help so I post it. Based on this answer I would go for a server that uses the same port for http and websocket connections. You can achieve it like this:

const { createServer } = require('http')
const ws = require('ws')
const express = require('express')

const app = express()

const server = createServer(app)

app.get('/', (req, res) => {
  res.send('I am a normal http server response')
})

const wsServer = new ws.Server({
  server,
  path: '/websocket-path',
})

wsServer.on('connection', (connection) => {
  connection.send('I am a websocket response')
})

server.listen(3030, () => {
  console.log(`Server is now running on http://localhost:3030`)
  console.log(`Websocket is now running on ws://localhost:3030/<websocket-path>`)
})

So your server listens on port 3030 for normal http requests. If it gets a websocket connection request on path '/websocket-path' it is passed to the the ws connection handler and from there you are good to go.

本文标签: javascriptWebsocket connection error returns 101but does not upgradeStack Overflow