Search code examples
typescriptazurewebsocketsignalr

Connecting to a SignalR WSS stream but not getting the response i am looking for


I am using Typescript on a next.js implementation of a client.

I am working on a connection to an Azure SignalR websocket. It's authenticated with a token and i am able to connect and ping successfully. I even get pongs back. However, I don't get the actual messages I am looking for - nothing gets received on the on(message) method.

I don't have access to the code of the server, but i do have a reference implementation and that does get the pong messages and the data message

Could the server be limited to broadcasting to one session ? or one session at a time - I am connecting with the same account, though the Auth token is different

I am quite stuck. I have duplicated all the inputs of the reference implementation, the socket connects and as i said , i send pings and get pongs back, but no data.

Note that the JWT token is passed in the url (wsUrl)

        const websocketInstance = new WebSocket(wsUrl, {
              headers: {
                Host: "******.signalr.net",
                  
            "Accept-Language": "en-GB,en;q=0.5",
            "Accept-Encoding": "gzip, deflate, br, zstd",
            "Sec-WebSocket-Version": "13",
            Origin: "********.com",
            "Sec-WebSocket-Extensions": "permessage-deflate",
            "Sec-WebSocket-Key": "********",
            Connection: "keep-alive, Upgrade",
            "Sec-Fetch-Dest": "empty",
            "Sec-Fetch-Mode": "websocket",
            "Sec-Fetch-Site": "cross-site",
            Pragma: "no-cache",
            "Cache-Control": "no-cache",
            Upgrade: "websocket",
              });
           websocketInstance.on("open", () => {..}
           websocketInstance.on("message", (data) => {..}
           websocketInstance.on("pong", (data) => {..}   
           websocketInstance.on("error", (error) => {..}
           ...
      }

Solution

  • As you're successfully connecting to Azure SignalR and getting pong responses, but you're not receiving actual messages.

    This happens because you're connecting directly via WebSockets (wss://), but SignalR requires an initial negotiation over https://.

    So, use https:// Instead of wss://

    • Send a POST request to https://your-signalr-service.signalr.net/client/negotiate.
    • Extract the urland accessToken from the response.
    • Use the extracted wss:// URL for your WebSocket connection.

    Here's a sample code:

    async function connectWebSocket() {
     
      const response = await fetch("https://your-signalr-service.signalr.net/client/negotiate", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
      });
      const { url, accessToken } = await response.json();
      const websocketInstance = new WebSocket(`${url}?access_token=${accessToken}`);
      websocketInstance.onopen = () => {
        console.log("WebSocket connection opened");
      };
      websocketInstance.onmessage = (event) => {
        console.log("Message received:", event.data);
      };
      websocketInstance.onclose = () => {
        console.log("WebSocket connection closed");
      };
      websocketInstance.onerror = (error) => {
        console.error("WebSocket error:", error);
      };
    
      return websocketInstance;
    }
    connectWebSocket();
    
    

    Please refer this doc for better understanding about Azure SignalR Service.

    As an alternative, you can use @microsoft/signalr instead of raw WebSockets, as it handles negotiation, tokens, and reconnection automatically.

    • Refer this doc1, doc2 to know about JavaScript & Typescript clients for SignalR.