Interact with Kaazing Gateway Using the WebSocket API

This section describes how you can use the WebSocket API provided by the Kaazing Gateway JavaScript client library (JavaScript Client API). This API allows you to take advantage of the WebSocket standard as described in the HTML5 specification and WebSocket API including the sending and receiving of string and binary messages.

The steps in this topic show you how to create a simple JavaScript client using the WebSocket API as implemented in the Kaazing JavaScript WebSocket library. The Kaazing JavaScript client library is fully-compliant with the WebSocket API standard and includes several enhancements. The JavaScript client you will create in this topic is the same as the JavaScript WebSocket Echo demo available on Github at https://github.com/kaazing/javascript.client.tutorials/tree/develop/ws.

For this example, we will use a publicly availble Kaazing WebSocket Gateway address wss://sandbox.kaazing.net/echo.

This topic covers the following information:

The examples in this topic highlight some of the most commonly used WebSocket methods. Refer to the JavaScript Client API for a complete description of all the available methods.

Before You Begin

This procedure is part of Checklist: Build JavaScript Clients Using Kaazing Gateway.

Note: Learn about supported browsers, operating systems, and platform versions in the Release Notes.

Supported Data Types

You can send a WebSocket message using one of the following data types:

Note: In the code examples in this topic, binaryType is specified in the send functions prior to sending binary data. This is to ensure that the received binary data will be of same binary type as the sent binary data. If you build an application that sends binary data (ArrayBuffer, Blob, ByteBuffer), you should specify binaryType based on the data type that you expect your received data will be. For example, you would set binaryType="arraybuffer" if you intend to receive binary message as ArrayBuffer.

To Use the WebSocket API with the Gateway

The following example demonstrates how to send and receive text and binary messages with the Gateway over WebSocket using a JavaScript client and the Gateway JavaScript Client API. The JavaScript client consists of an HTML page. You will add a script tag that points to the JavaScript WebSocket library from the HTML page, an HTML form, and the JavaScript needed to connect to the publicly available Gateway over WebSocket and send and receive WebSocket messages with the Echo service hosted on the Gateway.

  1. Clone or download the WebSocket demo from https://github.com/kaazing/javascript.client.tutorials.
  2. In a file browser, navigate to the folder containing the WebSocket demo, javascript.client.tutorials/ws.
  3. Create a new HTML page named echo.html and save it in the javascript.client.tutorials/ws folder.

  4. Copy and paste the following text and HTML form into the new echo.html file:

    <html>
    
    <head>
    
    </head>
    
    <body>
      <div class="main-container ">
        <div class="main wrapper clearfix">
          <!-- End header -->
          <article>
            <section class="demo">
              <!--  Kaazing scripts -->
              <div id="echo">
                <h1>JavaScript Echo Demo</h1>
                <p>This demo uses the WebSocket API to send
                  text messages to the Kaazing Gateway Echo service, which echoes back the messages.</p>
                  <div id="location-div" class="clearfix">
                    <div class="form-labels">
                      <label>Location</label>
                    </div>
                    <div class="form-fields">
                      <input id="wsurl" size="40">
                      <button id="connect">Connect</button>
                      <button id="close">Close</button>
                    </div>
    
                    <div id="logindiv">
                      <div class="heading clearfix">
                        <div class="text">Login</div>
                        <div class="image"><img src="images/lock-icon.png" width="56" height="56"></div>
                      </div>
                      <div class="clearfix">
                        <div class="form-labels">
                          <label for="username">Username:</label>
                        </div>
                        <div class="form-fields">
                          <input id="username" size="12" value=""/>
                        </div>
                      </div>
                      <div class="clearfix">
                        <div class="form-labels">
                          <label for="password">Password:</label>
                        </div>
                        <div class="form-fields">
                          <input id="password" type="password" size="12" value=""/><br>
                          <button id="login">OK</button>
                          <button id="cancel">Cancel</button>
                        </div>
                      </div>
                    </div> <!-- logindiv -->
    
                  </div> <!-- location-div -->
    
                  <div id="message-div" class="clearfix">
                    <div class="form-labels">
                      <label>Message</label>
                    </div>
                    <div class="form-fields">
                      <input id="message" size="40" value="Hello, WebSocket!"><br/>
                      <button id="sendText">Send Text</button>
                      <button id="sendBlob">Send Blob</button>
                      <button id="sendArrayBuffer">Send Array Buffer</button>
                      <button id="sendByteBuffer">Send Byte Buffer</button>
                    </div>
                  </div>
    
                  <div id="console-div">
                    Log messages
                    <div id="consoleLog"></div>
                    <button id="clear">Clear Log</button>
                  </div>
                </div> <!-- #echo -->
              </section>
            </article>
            <!-- Start footer -->
          </div> <!-- #main -->
        </div> <!-- #main-container -->
      </body>
    
    </html>
    

    Note the id in each form element. These ids will be used in your JavaScript code to reference user input and events.

  5. In the head section, add the following link tags for the CSS stylesheets:

    <link rel="stylesheet" href="css/normalize.css">
    <link rel="stylesheet" href="css/dev.css">
    <link rel="stylesheet" href="css/demo.css">
      
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    
  6. Save the HTML page.
  7. To see how the page looks, drag the echo.html file into a browser.
  8. In your HTML page named echo.html, add a script tag in the head section that points to the Kaazing JavaScript WebSocket library available on a content delivery network:

      <script src="http://cdn.kaazing.com/releases/enterprise.javascript.client/4.1.0/WebSocket.js"></script>
    

    For more information about where you can get the Kaazing JavaScript WebSocket library, see kaazing/download.

  9. After the script tag for the Gateway JavaScript WebSocket library, add a new script tag and a new JavaScript function named setup().
    <script>
    function setup() {
    
    }
    </script>
    

    This function will contain all of the JavaScript for the client. The function is named setup() because we will run the function when the page loads.

  10. Inside the setup() function, declare a variable for the WebSocket object:
    var websocket;
    
  11. Declare variables for the form elements:
    var locationURI = new URI("ws://sandbox.kaazing.net/echo");
    var consoleLog = document.getElementById("consoleLog");
    var clear = document.getElementById("clear");
    var wsurl = document.getElementById("wsurl");
    var message = document.getElementById("message");
    var connect = document.getElementById("connect");
    var sendText = document.getElementById("sendText");
    var sendBlob = document.getElementById("sendBlob");
    var sendArrayBuffer = document.getElementById("sendArrayBuffer");
    var sendByteBuffer = document.getElementById("sendByteBuffer");
    var close = document.getElementById("close");
    
  12. Set all of the buttons in the form as disabled when the page is loaded:
    // Enable or disable controls based on whether or not we are connected.
    // For example, disable the Connect button if we're connected.
    var setFormState = function (connected) {
    	wsurl.disabled = connected;
    	connect.disabled = connected;
    	close.disabled = !connected;
    	message.disabled = !connected;
    	sendText.disabled = !connected;
    	sendBlob.disabled = !connected;
    	sendArrayBuffer.disabled = !connected || (typeof(Uint8Array) === "undefined");
    	sendByteBuffer.disabled = !connected;
    }
    
  13. Next, we will add a function to display the log in the Log messages section of the client (the div tag with the id console-div). When the JavaScript client sends or receives messages, this function will be called and the sent and received messages are displayed in the Log messages section.
    wsurl.value = locationURI.toString();
    setFormState(false);
    var log = function (message) {
    	var pre = document.createElement("pre");
    	pre.style.wordWrap = "break-word";
    	pre.innerHTML = message;
    	consoleLog.appendChild(pre);
    	consoleLog.scrollTop = consoleLog.scrollHeight;
    	while (consoleLog.childNodes.length > 25) {
    		consoleLog.removeChild(consoleLog.firstChild);
    	}
    };
    
    var logResponse = function (message) {
    	log("<span style='color:blue'>" + message + "</span>");
    }
    
  14. Convert text strings into binary. Use the ByteBuffer object to enable the JavaScript client to convert text messages (strings) to binary before sending them. The messages sent using the JavaScript client are text messages. When you want to send these text messages as binary by clicking the Send Array Buffer button, you will need to convert the text string into a byte buffer first. A byte buffer is just an allocation of memory containing binary.
    // Takes a string and Returns an array of bytes decoded as UTF8
    var getBytes = function(str) {
        // Create a new ByteBuffer container for the binary data
        var buf = new ByteBuffer();
        // Encode a string into a ByteBuffer
        Charset.UTF8.encode(str, buf);
        /* Flip the buffer so that it can be read starting at 0,
        switching the buffer from writing mode to reading mode.
        */
        buf.flip();
        // Return the byte array to the sendArrayBuffer function
        return buf.array;
    }
    
  15. Add a functionat expression for when a user clicks Send Text.
    var doSendText = function () {
    	try {
    		var text = message.value;
    		log("SEND TEXT: " + text);
    		websocket.send(text);
    	} catch (e) {
    		log("EXCEPTION: " + e);
    	}
    };
    
    sendText.onclick = doSendText;
    
  16. Add an ArrayBuffer function for when a user clicks Send Array Buffer.

    Turning a text string into binary via a byte buffer provides you with a memory allocation of binary data, but it does not give you a context or view of the data, such as the data type, starting offset, and number of elements. Without that context, it is impossible to access the data stored in the buffer accurately. The ArrayBuffer as defined in the Typed Array Specification stores the data in a typed array and provides array buffer views to access the memory contained in the buffer. You use a ArrayBufferView mask, such as Uint8Array, to view, index and manipulate the raw binary of the ArrayBuffer. For a list of web browsers that support the Typed Array Specification, see caniuse.com.

    // Run this function when the Send Array Buffer button is clicked
    sendArrayBuffer.onclick = function() {
        try {
        /* Send the text message to the getBytes function,
        and get a byte array back
        */
        var bytes = getBytes(message.value);
        // View the byte buffer as an array of 8-bit unsigned integers
        var array = new Uint8Array(bytes);
        // Log the binary array
        log("SEND ARRAY BUFFER: " + array.buffer);
        // Identify the data type of the WebSocket connection as arraybuffer
        websocket.binaryType = "arraybuffer";
        // Send the array buffer over WebSocket
        websocket.send(array.buffer);
        } catch (e) {
        // Log exceptions
        log("EXCEPTION: "+e);
        }
    }
    
  17. Add a Blob function for when a user clicks Send Blob. Sending a blob uses BlobUtils, is a portable, cross-browser utility library for working with Blob instances. Blob is the default binaryType for WebSocket connections.
    // Run this function when the Send Blob button is clicked
    sendBlob.onclick = function() {
        try {
        /* Use BlobUtils to create a Blob from a string via UTF-8 encoding. 
        Returns a blob instance*/
        var blob = BlobUtils.fromString(message.value, "transparent");
        // Log the blob
        log("SEND BLOB: " + blob);
        // Identify the data type of the WebSocket connection as blob
        websocket.binaryType = "blob";
        // Send the blob over WebSocket
        websocket.send(blob);
        } catch (e) {
        log("EXCEPTION: "+e);
        }
    }
    
  18. Add a ByteBuffer function for when a user clicks Send Byte Buffer. ByteBuffer is available for JavaScript clients built using the legacy Kaazing Gateway JavaScript ByteBuffer library. Legacy clients can use the latest JavaScript WebSocket library without having to change their client code. The current WebSocket.js library is all that is needed. The current JavaScript WebSocket API enables clients to convert blob to and from Bytebuffer, thereby supporting the integration of blob binary messages in legacy clients.
    // Run this function when the Send Byte Buffer button is clicked
    sendByteBuffer.onclick = function() {
    try {
        // Create new ByteBuffer object
        var buf = new ByteBuffer();
        // Put the string into a byte buffer using UTF8 to encode the bytes
        buf.putString(message.value, Charset.UTF8);
        /* Flip the buffer so that it can be read starting at 0,
        switching the buffer from writing mode to reading mode.*/
        buf.flip();
        // Log the buffer
        log("SEND BYTE BUFFER: " + buf);
        // Identify the data type of the WebSocket connection as bytebuffer
        websocket.binaryType = "bytebuffer";
        // Send the buffer over WebSocket
        websocket.send(buf);
        } catch (e) {
        log("EXCEPTION: "+e);
        }
    }
    
  19. Add event handlers for the WebSocket connection and messages.
    var doConnect = function () {
    	log("CONNECT: " + wsurl.value);
    	connect.disabled=true;
    	try {
    		var factory = new WebSocketFactory();
    		websocket = factory.createWebSocket(wsurl.value);
    
    		websocket.onopen = function (evt) {
    			log("CONNECTED");
    			setFormState(true);
    			message.focus();
    		}
    
    		websocket.onmessage = function (evt) {
    			var data = evt.data;
    			if (typeof(data) == "string") {
    				//text
    				logResponse("RECEIVED TEXT: " + data);
    			}
    			else if (data.constructor == ByteBuffer) {
    				//bytebuffer
    				logResponse("RECEIVED BYTE BUFFER: " + data);
    			}
    			else if (data.byteLength) {
    				//arraybuffer
    				var u = new Uint8Array(data);
    				var bytes = [];
    				for (var i = 0; i < u.byteLength; i++) {
    					bytes.push(u[i]);
    				}
    				logResponse("RECEIVED ARRAY BUFFER: " + bytes);
    			}
    			else if (data.size) {
    				//blob
    				var cb = function (result) {
    					logResponse("RECEIVED BLOB: " + result);
    				};
    				BlobUtils.asNumberArray(cb, data);
    			}
    			else {
    				logResponse("RECEIVED UNKNOWN TYPE: " + data);
    			}
    		}
    
    		websocket.onclose = function (evt) {
    			log("CLOSED: (" + evt.code + ") " + evt.reason);
    			setFormState(false);
    		}
    
    	}
    	catch (e) {
    		connect.disabled=false;
    		log("EXCEPTION: " + e);
    		setFormState(true);
    	}
    };
    
    connect.onclick = doConnect;
    
    close.onclick = function () {
    	log("CLOSE");
    	websocket.close();
    };
    
    clear.onclick = function () {
    	while (consoleLog.childNodes.length > 0) {
    		consoleLog.removeChild(consoleLog.lastChild);
    	}
    };
    

    This is the last code entry in the setup() function.

  20. Below the closing brace of the setup() function, enter a new jquery function to load the JavaScript you wrote when the page loads.

    $(document).ready(function () {
    	setup();
    });
    
  21. Save the file.
  22. Test the JavaScript client. Drag the echo.html page into a web browser. The URL wss://sandbox.kaazing.net/echo is displayed in the Location field.
  23. Click Connect. The Log displays a successful connection to the Gateway. If there is an exception, review your code for possible errors.
  24. Click each of the send buttons and note the information displayed in the log.

    The following table provides examples of what the log should display for each button and the message “Hello, WebSocket!”.

    Button Message Returned
    Send Text RECEIVED: Hello, WebSocket!
    SEND TEXT: Hello, WebSocket!
    Send Blob RECEIVED BLOB: 72,101,108,108,111,44,32,87,101,98,83,111,99,107,101,116,33
    SEND BLOB: [object Blob]
    Send Array Buffer RECEIVED ARRAYBUFFER: 72,101,108,108,111,44,32,87,101,98,83,111,99,107,101,116,33
    SEND ARRAY BUFFER: [object ArrayBuffer]
    Send Byte Buffer RECEIVED BYTEBUFFER: 48 65 6c 6c 6f 2c 20 57 65 62 53 6f 63 6b 65 74 21
    SEND BYTE BUFFER: 48 65 6c 6c 6f 2c 20 57 65 62 53 6f 63 6b 65 74 21
  25. Click Close to close the WebSocket connection.

Setting and Overriding HttpRedirectPolicy Defaults on the WebSocketFactory

You can set a default redirect-policy on the WebSocketFactory that enables you to determine how your application handles server redirects. For example, you can set the client application to never follow HTTP redirects. All the WebSockets created using that factory automatically inherit the default. You can then override the defaults on an individual WebSocket, if desired. The Kaazing Gateway JavaScript API also provides the following options:

Option Description
NEVER Do not follow HTTP redirects.
ALWAYS Follow the HTTP redirect requests always, regardless of the origin, domain, etc.
SAME_ORIGIN Follow the HTTP redirect only if the origin of the redirect request matches. This implies that both the scheme/protocol and the authority between the current and the redirect URIs should match. The port number should also be the same between the two URIs.
SAME_DOMAIN Follow HTTP redirect only if the domain of the redirect request matches the domain of the current request. For example, URIs with identical domains would be ws://production.example.com:8001 and ws://production.example.com:8002.
PEER_DOMAIN Follow the HTTP redirect only if the redirected request is for a peer-domain. For example, the domain in the URI ws://sales.example.com:8001 is a peer of the domain in the URI ws://marketing.example.com:8002.
SUB_DOMAIN Follow the HTTP redirect only if the request is for sub-domain. For example, the domain in the URI ws://benefits.hr.example.com:8002 is a sub-domain of the domain in the URI ws://hr.example.com:8001.

You can specify HttpRedirectPolicy on the WebSocketFactory such that it will be inherited by all the WebSockets that are created using the factory. The following example shows HttpRedirectPolicy.SAME_DOMAIN as the default redirect policy set on the WebSocketFactory. So, all the WebSockets created using the factory will inherit the same redirect policy that was specified on the WebSocketFactory.

var webSocketFactory = new WebSocketFactory();
webSocketFactory.setDefaultRedirectPolicy(HttpRedirectPolicy.SAME_DOMAIN);
var webSocket = webSocketFactory.createWebSocket(“ws://localhost:8001/echo”);

You can also override the inherited HttpRedirectPolicy by specifying it directly on the WebSocket. The following example shows the redirect policy on the individual WebSocket can be overridden to HttpRedirectPolicy.PEER_DOMAIN.

var webSocketFactory = new WebSocketFactory();
webSocketFactory.setDefaultRedirectPolicy(HttpRedirectPolicy.SAME_DOMAIN);
var webSocket = webSocketFactory.createWebSocket(“ws://localhost:8001/echo”);
webSocket.setRedirectPolicy(HttpRedirectPolicy.PEER_DOMAIN);

See Also

WebSocket API documentation