Saturday, May 5, 2018

Connect to a socket.io server from a Node.js server using the 'ws' package

Leave a Comment

I have a Node.js server which utilizes the popular ws package for using web sockets. I'd like to use this library to connect to an third party server which is running socket.io.

If I were to use socket.io on my server, the connection code would be something like this:

const socket = socketIo('https://api.example.com/1.0/scores') 

I've attempted to connect to the same service using the ws package, and modifying the url:

const wsClient = new WebSocket('wss://api.example.com/1.0/scores'); 

but this results in the following:

Error: Unexpected server response: 200

Question: What needs to be done to connect to a third party server running socket.io from a server running the ws package?

Additional Info:

  • I've noticed in my searches that some people have suggested appending /socket.io/?EIO=3&transport=websocket to the end of the url. This does not throw the same error as above (> Error: Unexpected server response: 200) nor throw any visible error, but does not appear to work (no data is received from the remote server).
  • Using new WebSocket('ws://api.example.com/1.0/scores?EIO=3&transport=websocket'); to open the connection (via ws) results in the following stack trace:

    { Error: Parse Error     at Socket.socketOnData      at emitOne      at Socket.emit      // ...  } 

2 Answers

Answers 1

Because Socket.IO doesn't guarantee that there will be a WebSockets server hosted like you're seeming to expect, you should instead use their standard client package.

npm i socket.io-client 

Then use the package in your code:

const ioClient = require('socket.io-client')('https://example.com/1.0/scores') 

The full docs for socket.io-client are available on their GitHub repo.

Note: Honestly, though, it's just better at this point to use WebSockets instead if possible. WebSockets has become very well supported in browsers and is quite standard. Socket.IO is rarely necessary and is just bulky.

Answers 2

The socket.io api utilizes websockets but it also has a lot of other functions built on top of it in order to do things such as HTTP handshakes, session ids, and it can even handle fail overs to other protocols when needed.

You got half of the issue so far. Adding the line socket.io/?EIO=3&transport=websocket you're specifying parameters for the socket.io server to take.

EIO=3 specifies the version number for engine.io in which socket.io is using. In this case you are saying engine.io version = 3

transport=websocket specifies which transport protocol to use. As i said earlier, socket.io uses other protocols in cases such as fail overs. This portion forces socket.io to use websocket as the preferred protocol.

Now the next half is the WebSocket api itself. WebSocket allows for Extensions which includes different kinds of compression that are commonly used when sending data. Which I believe is what is causing your Parse Error

Try this (found here):

const WebSocket = require('ws'); const ws = new WebSocket('ws://server/socket.io/?EIO=3&transport=websocket', {    perMessageDeflate: false }); 

By setting perMessageDeflate: false you are specifying "Do not compress data". Since as i said this is a WebSocket Extension there are different variations as well. Try these instead if it doesn't work

  • x-webkit-deflate-frame
  • perframe-deflate

As a disclaimer this information is from the research that I have done. Im not a "socket.io specialist" so if there's anything i got wrong or missed please tell me and i'll edit the post.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment