kataras / neffos.js

Node.js and Browser support for the neffos real-time framework written in Typescript.
MIT License
42 stars 16 forks source link

Uncaught Error for declining connection initialization at "OnNameSpaceconnect" #7

Open mbecker opened 5 years ago

mbecker commented 5 years ago

Hi,

I'm declingin the initialiation the connection of the websocket to a namespace as follows:

var serverEvents = websocket.Namespaces{
    namespace: websocket.Events{
        websocket.OnNamespaceConnect: func(nsConn *websocket.NSConn, msg websocket.Message) error {
            return fmt.Errorf("No role 'admin'")
        },
        websocket.OnNamespaceConnected: [...]

At the client side the connection initialization is from the examples as follows:

async function runExample() {
        try {
          const conn = await neffos.dial(
            wsURL,
            {
              default: {
                // "default" namespace.
                _OnNamespaceConnect: function(nsConn, msg) {
                  console.log(nsConn);
                  console.log(msg);
                },
                _OnNamespaceConnected: function(nsConn, msg) {
                  addMessage("connected to namespace: " + msg.Namespace);
                  handleNamespaceConnectedConn(nsConn);
                },
                _OnNamespaceDisconnect: [...]

The error from the js library is as follows:

Uncaught (in promise) Error: No role 'admin'
at deserializeMessage (neffos.min.js:1)
at a.handleMessage (neffos.min.js:1)
at a.handle (neffos.min.js:1)
at WebSocket.i.onmessage (neffos.min.js:1)

My use case is that I want only allow specific users the connection to a websocket namespace. On the client side the returned error should be caught and sent to the end user properly.

Did I cancel the initialization of the websocket connection to the namespace in the correct way?

kataras commented 5 years ago

Hello @mbecker and sorry for the delay,

What do you mean by "the returned error should be caught and sent to the end user properly"? This is done on server's websocket.OnNamespaceConnect event callback as you do, if you want to check for specific user check its nsConn fields which you can get the Conn and its http.Request (if you need to disallow clients in connecting at all you should use the server#OnConnect event instead which is fired before namespace connect).

However, if you mean the issue is the error log you posted above then you should check the catch of try {...} catch(err){ /* HERE */ }, I think you console.error/log the error and that's why you see this error on your debug window.

mbecker commented 5 years ago

Hi @kataras ,

I'm sorry the code above is just an extract from your example here in the repos. The full javascript code is as follows:

async function runExample() {
  // You can omit the "default" and simply define only Events, the namespace will be an empty string"",
  // however if you decide to make any changes on this example make sure the changes are reflecting inside the ../server.go file as well.
  try {
    const conn = await neffos.dial(
      wsURL,
      {
        default: {
          // "default" namespace.
          _OnNamespaceConnect: function(nsConn, msg) {
            console.log(nsConn);
            console.log(msg);
          },
          _OnNamespaceConnected: function(nsConn, msg) {
            addMessage("connected to namespace: " + msg.Namespace);
            handleNamespaceConnectedConn(nsConn);
          },
          _OnNamespaceDisconnect: function(nsConn, msg) {
            addMessage("disconnected from namespace: " + msg.Namespace);
          },
          vehicles: function(nsConn, msg) {
            // "vehicles" event.
            addMessage(msg.Body);
          }
        }
      },
      {
        headers: {
          "X-Username": username
        }
      }
    );

    // You can either wait to conenct or just conn.connect("connect")
    // and put the `handleNamespaceConnectedConn` inside `_OnNamespaceConnected` callback instead.
    // const nsConn = await conn.connect("default");
    // nsConn.emit(...); handleNamespaceConnectedConn(nsConn);
    conn.connect("default");
  } catch (err) {
    handleError(err);
  }
}
function handleError(reason) {
  console.log(reason);
  window.alert("error: see the dev console");
}

Thanks for the explanation in your first paragraph. My use case is to restrict just specific namespace on the backend; that's why I'm returning an error on the server's websocket.OnNamespaceConnect as follows:

websocket.OnNamespaceConnect: func(nsConn *websocket.NSConn, msg websocket.Message) error {
  return fmt.Errorf("No role 'admin'")
}

I mean with the following sentences

the returned error should be caught and sent to the end user properly

that the returned error No role 'admin' on the backend / service side should be communicated to the javascript client. At the client side I would catch that specifc error message.

The sequence would be as follows:

Javascript Client -> Connection to WS Server Namespace -> WS Server returns error for establishing connection to namespace -> Send back error to client -> Client catches error

Maybe I'm missing something. Any help or hint would be awesome. Thanks!