bun icon indicating copy to clipboard operation
bun copied to clipboard

Simple script to connect to WebSocket not working in Bun but working in Node

Open 0x4a61636f62 opened this issue 3 years ago • 9 comments

Version

v0.1.11

Platform

Microsoft Windows NT 10.0.22000.0 x64

What steps will reproduce the bug?

Run the following code:

const url = "wss://stream.data.alpaca.markets/v2/iex";
const socket = new WebSocket(url);
socket.onmessage = function(event) {
  console.log("on message event triggered");
  const data = JSON.parse(event.data);
  console.log("On message event: ", data[0]);
  if (data[0]["msg"] === "authenticated") {
    console.log("Do authentication");
  }
}

How often does it reproduce? Is there a required condition?

  • No required conditions.
  • Always reproducible.

What is the expected behavior?

Running the code should output to the console:

on message event triggered On message event: { T: 'success', msg: 'connected' }

What do you see instead?

Using the below I see that the code attempts to connect, and then the readyState immediately moves to closed. The onmessage event does not get fired. Of course, as expected, I get the same result if simply listening to the emitted events without the async function.

async function awaitOpenConnection(socket: WebSocket): Promise<string> {
    /*For testing purposes********************* */
    console.log("Socket object: ", socket);
    socket.onmessage = function(event) {
      console.log("On message event: ", event.data);
    }
    /****************************************** */
    return new Promise((resolve, reject) => {
      if (socket.readyState === socket.CONNECTING) {
        console.log("Socket connecting...");
      }
      socket.onopen = () => {
        resolve(`Connection open`);
      }
      socket.onclose = () => {
        switch (socket.readyState) {
          case socket.CLOSED:
            reject(`Connection closed`);
            break;
          case socket.CLOSING:
            reject(`Connection closing`);
            break;
        }
      }
      socket.onerror = () => {
        reject(`Error establishing connection`);
      }
    });
  }

Additional information

  • I am Running Bun in Ubuntu 20.04(WSL).
  • I can confirm that the code is working in Node and results in the expected behaviour.
  • I cannot confirm if this is an issue with other WebSockets addresses other than wss://stream.data.alpaca.markets/v2/iex as I have not tried it.
  • I have tried to change my firewall settings in Windows but the result is the same.

If I listen to the events:

streamClient.connect();

streamClient.onConnecting(
  () => console.log("Connecting...")
);

streamClient.onConnect(
  () => console.log("Connected")
);

streamClient.onStateChange(
  (state) => console.log(`State changed to ${state}`)
)

streamClient.onError(
  (error) => console.log(`Error: ${error}`)
)

This is what I see:

State changed to disconnected
State changed to waiting to reconnect
State changed to connecting
Connecting...
State changed to disconnected
State changed to waiting to reconnect
State changed to connecting
Connecting...
State changed to disconnected
State changed to waiting to reconnect
State changed to connecting
Connecting...
State changed to disconnected
State changed to waiting to reconnect
State changed to connecting
Connecting...
State changed to disconnected
State changed to waiting to reconnect
State changed to connecting
Connecting...
State changed to disconnected
State changed to waiting to reconnect

0x4a61636f62 avatar Sep 14 '22 21:09 0x4a61636f62

@Jarred-Sumner I forgot to mention one very important thing. This is a WebSocket to get stock market data, which means that pre-market, i.e., before 9:30 AM in New York or during weekends, the Websocket will never connect. Unless this is a common bug, it is tedious to test since you can only do it during market opening hours.

Some additional information:

wss://stream.data.alpaca.markets/v2/iex The IEX source can be connected and authenticated without a subscription plan.

wss://stream.data.alpaca.markets/v2/sip The SIP data source can connect to without a subscription plan but not authenticate.

Also for your reference, here are the docs, although I doubt they will be of much help. https://alpaca.markets/docs/api-references/market-data-api/stock-pricing-data/realtime/

0x4a61636f62 avatar Sep 16 '22 23:09 0x4a61636f62

In Bun v0.1.12 it will report a reason and code which should get a little closer to the cause

Jarred-Sumner avatar Sep 17 '22 08:09 Jarred-Sumner

I tried again after v0.1.13, and the result is the same as reported above.

Upon socket.onclose the code is 1001 and the reason is Closed by server.

The meaning of the code according to the protocol is: An endpoint is "going away", such as a server going down or a browser having navigated away from a page.

We know the server is not going away since it works fine connecting in Node. But it is hard to say what "browser having navigated away from a page" means in our context.

0x4a61636f62 avatar Sep 19 '22 17:09 0x4a61636f62

I think the issue is fixed by https://github.com/oven-sh/bun/commit/c2c9173eff9e929004d73e087b62ffdc25f0f4ee

Jarred-Sumner avatar Oct 08 '22 08:10 Jarred-Sumner

Thanks, @Jarred-Sumner! I will test it on Monday next week.

0x4a61636f62 avatar Oct 08 '22 23:10 0x4a61636f62

@Jarred-Sumner I have retested this issue, but unfortunately, the issue seems to be the same, i.e. it is "connecting" and then closes without the client receiving any message.

0x4a61636f62 avatar Oct 11 '22 16:10 0x4a61636f62

@robobun

const url = "wss://stream.data.alpaca.markets/v2/iex";
const socket = new WebSocket(url);
socket.onmessage = function(event) {
  console.log("on message event triggered");
  const data = JSON.parse(event.data);
  console.log("On message event: ", data[0]);
  if (data[0]["msg"] === "authenticated") {
    console.log("Do authentication");
  }
  socket.close();
}

Electroid avatar Jan 18 '23 08:01 Electroid

@Electroid here you go!

on message event triggered
On message event:  {
  T: "success",
  msg: "connected"
}
Code
const url = "wss://stream.data.alpaca.markets/v2/iex";
const socket = new WebSocket(url);
socket.onmessage = function(event) {
  console.log("on message event triggered");
  const data = JSON.parse(event.data);
  console.log("On message event: ", data[0]);
  if (data[0]["msg"] === "authenticated") {
    console.log("Do authentication");
  }
  socket.close();
}

Ran using the latest build of Bun, an all-in-one JavaScript runtime.

robobun avatar Jan 18 '23 08:01 robobun

This appears to work as of Bun v0.5.0, at least on MacOS and Linux. Does this still happen when you try again?

bun upgrade --canary

Electroid avatar Jan 18 '23 08:01 Electroid

Tested again, marking as fixed. Let us know if you are still able to reproduce this issue.

Electroid avatar Feb 27 '23 17:02 Electroid