Connection Cascading in the JavaScript Unified Client

In Diffusion 5.7, we added a polling (XHR) transport to the existing WebSocket transport. XHR is short for XMLHttpRequest which is an API provided by the browsers for a server and a client to exchange data.

A new option, ‘transports’, that the JavaScript client can use to pass in a list of transports to connect to the server, for example:

diffusion.connect({
    transports : ['WS', 'XHR'],
    host : 'localhost',
    trace: true,
    port   : 8080,
    secure : false,
    principal : 'admin',
    credentials : 'password'
}).then( // returned Promise);

This indicates that the client will use the WebSocket transport to connect to the server. If WebSocket is not available in the browser or is blocked, the client will retry with the XHR transport.

What happens if the ‘transports‘ option is left out?

The client will use WebSocket transport by default when no list is provided.

However, when the client is supplied with an empty transports list then no transport will be used and the client will not be able to connect to the server.

It became desirable that when the client could not connect to the server with a transport – for example, because the server rejected the connection request due to, say, a transport error – then the client should automatically cascade down to the next transport from the list.

There can only be two outcomes with client connection establishment:

  1. cascade – the client picks the next transport from the list
  2. fail – the client stops trying to connect and logs out the result

The client will cascade in the order specified in the transport list and will not retry the last transport if all transports fail. For example, for the transports list:

diffusion.connect({
    transports : ['WS', 'XHR'],
    ...
}).then( // returned Promise);

The client will cascade from WS down to XHR then stop if the connection attempt failed, and not loop back to WS as a final try.

Users can specify a transport more than once in the transports list, such as:

diffusion.connect({
    transports : ['WS', 'XHR', 'WS'],
    ...
}).then( // returned Promise);

as a way to retry the last transport, if wanted.

A transport can be tried several times in a row, for example:

diffusion.connect({
    transports : ['WS', 'WS', 'WS', 'WS'],
    ...
}).then( // returned Promise);

This will tell the client to use the WebSocket transport to connect to the server four times after each connection attempt failed to establish a connection.

Cascade logic

The client should not cascade regardless of the response code it receives from the server when a connection request is rejected. For example, when the client receives a response with code 116 – authentication failed, there is little point in trying to connect again or to cascade down to other transport as the credentials and password are still wrong. This will need to be handled by the application and most likely need intervention by the user.

We can divide the server response code list into two distinct categories: fatal error and transport error.

Fatal error

This error indicates that the client should not cascade. When the client receives a server’s response that is a fatal error, it should not cascade down to other available transports.

Transport error

This error indicates that the client should cascade to other transports from the list as the request could be dropped by a load balancer because a WebSocket header was stripped out.

The client is implemented to perform connection cascading if the response code from the server matches any from the table below:

Response Code Description
ERROR Connection failed due to server error
UNKNOWN_SESSION Reconnection failed – the session is unknown
LICENSE_EXCEEDED Connection rejected due to license limit

Otherwise, the client will cease to cascade.

Cascading securely

The connection cascading also works with HTTPS when client is loaded in a HTTPS web page. What the client cannot do is to cascade from a secure transport to an insecure transport. The client does not support this as the host and port are not changeable in between connections. This is unlikely to be changed in the future.

Learn more about how Push Technology’s realtime messaging solution, Diffusion, works or download it now.