pladaria / reconnecting-websocket

Reconnecting WebSocket. For Web, React Native, cli (Node.js)
MIT License
1.22k stars 197 forks source link

Cannot access underlying WebSocket #23

Closed bnielsen1965 closed 7 years ago

bnielsen1965 commented 7 years ago

I am using the npm ws Websocket in a node.js app and I would like to use the Websocket.ping() method to keep my connection alive. However, the ping() method is not implemented in ReconnectingWebsocket and I don't see a way to access the Websocket instance that was created within ReconnectingWebsocket.

Would you be open to adding a method or property that provides access to the underlying Websocket? That would make any current or future methods and/or properties in a Websocket implementation available while still using ReconnectingWebsocket.

The other option would be to implement the ping method, but it may not be supported in all Websocket implementations just yet.

pladaria commented 7 years ago

reconnecting-websocket implements the WebSocket Web API Interface.

There's no ping method in that interface (see discussion).

Consider moving the ping handling to an upper layer, for example, if you were implementing a XMPP chat client over WebSocket, the ping mechanism is part of the XMPP protocol. Simply send a regular message with a ping payload and make the server respond to it.

bnielsen1965 commented 7 years ago

Unfortunately I am not using reconnecting-websockets in a web browser, the RFC 6455 specification is more applicable to my situation.

I can understand not wanting a ping method where it does not exist in the WebSocket API, but it does exist in non-browser APIs that have implemented RFC 6455. But this API is not accessible because the ReconnectingWebsocket does not provide access to the underlying WebSocket that is created using the provided constructor.

However, after reading the discussion about ping/pong I am beginning to wonder if it might be better to have the ping/pong handled within the Websocket API. That would be better than having every application provide their own unique ping/pong implementation.

pladaria commented 7 years ago

Can you please give me more details about how are you using reconnecting-websocket?

Are you using html5-websocket, ws or any other websocket lib?

bnielsen1965 commented 7 years ago

I am using ws on a client and server application so I have something like the following on the client...

var WebSocket = require('ws');
var ReconnectingWebSocket = require('reconnecting-websocket');
var rws = new ReconnectingWebSocket(
  'ws://10.69.0.86:8080/', 
  null, 
  { constructor: WebSocket }
);

The ws WebSocket implementation includes the ping/pong as noted in the RFC and will respond with a pong frame when it receives a ping frame as outlined in the specification but the application must initiate with the ping() call. And this requires access to the WebSocket instance.

What I initially implemented was a ReconnectingWebsocket.getWebsocket() method that returns the ws instance. From there my application can call ws.ping() to initiate the ping/pong process. And listen to the ReconnectingWebSocket for a pong response.

However, after reading the discussion you linked I'm not sure this is the best solution. In the browser implementation it is the browser that handles the keep alive and socket termination. So it seems like it would be better to have an option in the ws WebSocket implementation for a ping/pong keep alive process that closes the socket if the ping/pong fails. From there ReconnectingWebSockets would see the close and respond as expected.

This has been mentioned a few times in ws WebSocket discussions and there is a PR for a server side implementation. Unfortunately the PR seems to be dead and it does not go far enough because it needs to include the client side. But this seems like the correct location for the ping/pong implementation.

pladaria commented 7 years ago

I had problems passing ws as constructor. If you use it in the reconnecting-websocket test suite, almost no test will pass. I need to investigate but I guess this is related on how ws cleans the resources after disconnecting. For now, I would recommend to use html5-websocket for node environments.

Freakachoo commented 4 years ago

I've found that ws._ws.ping() perfectly works. It seems like ws._ws is the reference to underlying WebSocket.