awslabs / amazon-kinesis-video-streams-webrtc-sdk-js

JS SDK for interfacing with the Amazon Kinesis Video Streams Signaling Service.
https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html
Apache License 2.0
288 stars 145 forks source link

Support handling/catching websocket errors #41

Open suggestedfixes opened 4 years ago

suggestedfixes commented 4 years ago

Currently, we have observed websocket errors in console mode. The context was we have a periodic check on ice connection status and aggregated connection status on the front end and make a new peer during reconnection. It might have occurred when we unplug wifi or restart the master while viewer is connected. Our question is that is there a way to catch websocket errors such as following?

chunk-vendors.79b6f08a.js:60 WebSocket connection to 'wss://v-dc297268.kinesisvideo.us-east-2.amazonaws.com/?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-ChannelARN=arn%3Aaws%3Akinesisvideo%3Aus-east-2%3A465671368404%3Achannel%2F1C8259185F66%2F1584462043105&X-Amz-ClientId=Client7869&X-Amz-Credential=ASIAWY3BNF3KHBMQBF4S%2F20200508%2Fus-east-2%2Fkinesisvideo%2Faws4_request&X-Amz-Date=20200508T141951Z&X-Amz-Expires=299&X-Amz-Security-Token=FwoGZXIvYXdzELD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDEs8S1PdPv%2FzumBA6yKAAgiUqJC9YxgnswRryrCKBsVzVuugs8A%2F1dsIiDmTOH5whheyc672MeCMWaSGhTRJ9Vu2InHuJc5VFZMwFKPoTCVeZgp0QAhGteLLcnXYYuTFWgneIsOLcgxJFyjcTsjIRM0GF75xtNtrS1iLw9NwnodbA2WC%2F71Z7Mx9qr7JwOYG0nEjdVfcJ2G0dK%2BACu4scTKcX6fQnBw7D4Acdr1Ex%2BxVGY1WfWQwerz7uqYqhFZmNbAYvD97%2BGLuvVAU5hCc%2FB6wh4JE3PbqWbJVIIouo%2FdPvUGPSgXzwWvrknr5w1Wk698xMRk1xhWc64soTphpNHor7LWFj2Z4LwihAxzD6ZEohdXV9QUyLf23GzxiimYYTPDpLNsZPMFMR6y3qRp6FVjjKBEAT7L4CxnHuAMWlhr9wmByAA%3D%3D&X-Amz-Signature=957d365313b7622132b213236f02c3e181358ebe383ee665522432995be9a9cf&X-Amz-SignedHeaders=host' failed: Error during WebSocket handshake: Unexpected response code: 400
suggestedfixes commented 4 years ago

We were also able to print a subset of websocket errors through clientInstance.on('error', callback), one such example is:

Event {isTrusted: true, type: "error", target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
bubbles: false
cancelBubble: false
cancelable: false
composed: false
currentTarget: WebSocket {url: "wss://v-dc297268.kinesisvideo.us-east-2.amazonaws.…36a2fafd25a96fa0aeac3dd0&X-Amz-SignedHeaders=host", readyState: 3, bufferedAmount: 0, onopen: null, onerror: null, …}
defaultPrevented: false
eventPhase: 0
isTrusted: true
path: []
returnValue: true
srcElement: WebSocket {url: "wss://v-dc297268.kinesisvideo.us-east-2.amazonaws.…36a2fafd25a96fa0aeac3dd0&X-Amz-SignedHeaders=host", readyState: 3, bufferedAmount: 0, onopen: null, onerror: null, …}
target: WebSocket {url: "wss://v-dc297268.kinesisvideo.us-east-2.amazonaws.…36a2fafd25a96fa0aeac3dd0&X-Amz-SignedHeaders=host", readyState: 3, bufferedAmount: 0, onopen: null, onerror: null, …}
timeStamp: 9966.775000095367
type: "error"
__proto__: Event

I suppose the goal we are asking is how to contain/capture this in a try/catch phrase or promise catching so that we can handle a particular code path when needed.

lherman-cs commented 4 years ago

@suggestedfixes From my understanding, you're trying to encapsulate "connect" as a promise and call it inside of a try/catch?

If that's the case I would probably do something like,


function connect() {
  const signalingClient = new KVSWebRTC.SignalingClient({...});
  return new Promise((resolve, reject) => {
    signalingClient.on('open', () => {
      ...
      resolve(signalingClient);
    });
    signalingClient.on('error', (err) => {
      reject(err);
    });
  });
}

(async () => {
  try {
    const client = await connect();
  } catch (e) {
    // do something here with the error
  }

  // reset the error callback with your custom error handling
  client.on('error', (err) => { ... }));
})()
lherman-cs commented 4 years ago

@suggestedfixes does my snippet work for you? If yes, do you mind to close this issue?

suggestedfixes commented 4 years ago

We are using a different platform (vue.js) and uses a different teardown method. I think this maps onDestory() handler of vue.js. Ignore my post, intended to answer another thread.

suggestedfixes commented 4 years ago

I'm trying to contain the error so that the console doesn't complain. I have attempted the following and it didn't work very well. I will give your method an attempt.

client('on', (error) => {
    try {
    } catch (error) {
    }
});

I think I have attempted the following and it didn't work. But since I don't remember I will give this a try as well.

signalingClient.on('error', (err) => {
      err.preventDefault();
});
suggestedfixes commented 4 years ago

One thing I have not tried is probably something similar to this, the pseudo javascript code would be something similar to this but It might not work.

client.on('error', async (err) => {
}.catch((err) => {
})
lherman-cs commented 4 years ago

@suggestedfixes is there more updates on this?

sirknightj commented 1 year ago

For some context, the easiest way to replicate this is to just give an invalid signed URL into WebSocket constructor.

The browser currently doesn't expose the HTTP response or error code back when there is a WebSocket connection failure.

https://stackoverflow.com/questions/23011900/how-to-access-websocket-response-headers-in-javascript https://stackoverflow.com/questions/43141900/get-full-response-of-websocket-connect https://stackoverflow.com/questions/21762596/how-to-read-status-code-from-rejected-websocket-opening-handshake-with-javascrip https://stackoverflow.com/questions/31002592/javascript-doesnt-catch-error-in-websocket-instantiation

Regarding the {"isTrusted":true}, https://stackoverflow.com/questions/44815172/log-shows-error-object-istrustedtrue-instead-of-actual-error-data