docs.intersystems.com
InterSystems IRIS Data Platform 2019.2  /  Web Gateway Configuration Guide  /  Web Gateway Operation and Configuration

Web Gateway Configuration Guide
Using WebSockets (RFC 6455)
Previous section           Next section
InterSystems: The power behind what matters   
Search:  


Using WebSockets (RFC 6455)
The web has been built around the request/response paradigm: the client sends a request to the server and the server reacts by sending a response to the client. This paradigm, and HTTP itself, does not allow for an inverted form of this communication protocol whereby a server initiates a request/response cycle with the client. A number of technologies have been developed to create an illusion that a server can initiate a dialogue with a client. These technologies are generally known as push-based or comet-based technologies and all suffer from problems that make them unsuitable for general deployment over web infrastructure. The three main techniques in current use are described below.
Short Polling
With this technique a client regularly sends HTTP requests to detect changes in server state, and the server is programmed to responds immediately. An empty response signifies no change.
Problems:
Long Polling
With this technique a client sends a HTTP request but the server only responds when the client needs to be notified of a change. The client typically sends another “Long Poll” request as soon as the server sends a response message.
Problems:
HTTP Streaming
This technique takes advantage of the HTTP protocol’s ability to maintain persistent (or ‘KeepAlive’) connections between the client and server. The client sends an HTTP request which is permanently kept open with the server only responding when the client needs to be notified of a change. The server does not terminate the connection after dispatching a response message and the client waits for the next message from the server (or sends a message of its own to the server).
Problems:
WebSockets Protocol
The WebSockets protocol (RFC 6455) addresses the fundamental requirement of allowing servers to proactively push messages to clients by providing a full-duplex message-oriented communications channel between a client and its server. The protocol is designed to operate, and hence be secured, over the standard TCP channel already established between the client and server and used to support the HTTP protocol between a web browser and web server.
The WebSockets protocol and its API are standardized by the W3C and the client part is included with HTML 5.
Intermediaries, such as proxies and firewalls, are expected to be aware of, and to support, the WebSockets protocol.
Browser Support
There have been several iterations in creating the final standard for the WebSockets protocol, each with varying degrees of browser support. The history is summarized below.
The HyBi-17/RFC 6455 section is the most significant for the purpose of developing portable web applications.
Server Support
The latest versions of all major web servers offer WebSockets support as shown below:
Protocol in Detail
Creating a WebSocket involves an ordered exchange of messages between the client and the server. First, the WebSocket handshake must take place. The handshake is based on, and resembles, an HTTP message exchange so that it can pass without problem through existing HTTP infrastructure.
The web server recognizes the conventional HTTP header structure in the handshake request message and sends a similarly constructed response message to the client indicating that it supports the WebSocket protocol - assuming it is able to. If both parties agree then the channel is switched from HTTP (http://) to the WebSockets protocol (ws://).
Typical WebSocket Handshake Message from Client
GET /csp/user/MyApp.MyWebSocketServer.cls HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://localhost
Typical WebSocket Handshake Message from Server
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
Note how the client handshake message requests that the protocol be upgraded from HTTP to WebSocket. Note also the exchange of unique keys between the client (Sec-WebSocket-Key) and server (Sec-WebSocket-Accept).
WebSockets Client Code (JavaScript)
In the browser environment the client side of the WebSockets protocol is implemented in JavaScript code. Standard text books describe the usage model in detail. This document briefly describes the basics.
Create a WebSocket
The first parameter represents the URL identifying the server end of the WebSocket application. The second parameter is optional, and if present, specifies the sub-protocol that the server must support for the WebSocket connection to be successful.
var ws = new WebSocket(url, [protocol]);
Example:
ws = new WebSocket(((window.location.protocol == "https:")
     ? "wss:" : "ws:") \
     + "//" + window.location.host
     + /csp/user/MyApp.MyWebSocketServer.cls);
Note how the protocol is defined as either ws or wss depending on whether or not the underlying transport is secured using SSL/TLS.
The read-only attribute ws.readyState defines the state of the connection. It can take one of the following values:
The read-only attribute ws.bufferedAmount defines the number of bytes of UTF-8 text that have been queued using the send() method.
WebSocket Events
The following events are available.
Data received in event.data.
WebSocket Methods
The following methods are available.
WebSockets Server Code
The base InterSystems IRIS class for implementing WebSocket Servers is %CSP.WebSocket
When the client requests a WebSocket connection, the initial HTTP request (the initial handshake message) instructs the CSP engine to initialize the application's WebSocket server. The WebSocket server is the class named in the requesting URL. For example, if your WebSocket server is called MyApp.MyWebSocketServer and is designed to operate in the USER namespace then the URL used to request the WebSocket connection is:
/csp/user/MyApp.MyWebSocketServer.cls
WebSocket Events
The implementation of the WebSocket server is derived from the base %CSP.WebSocket class. There are three key methods to implement as responses to the following events. Note that the web session is unlocked before calling any of these methods.
OnPreServer (optional)
Use this method to invoke code that should be executed before the WebSocket server is established. Changes to the SharedConnection property must be made here.
Server (Mandatory)
The WebSocket server. This is the server-side implementation of the WebSocket application. Messages can be exchanged with the client using the Read() and Write() methods. Use the EndServer() method to gracefully close the WebSocket from the server end.
OnPostServer (optional)
Use this method to invoke code that should be executed after the WebSocket server has closed.
WebSocket Methods
The following methods are provided
Method Read(ByRef len As %Integer = 32656,
     ByRef sc As %Status,
     timeout As %Integer = 86400) As %String
This method reads up to len characters from the client. If the call is successful the status (sc) is returned as $$$OK; otherwise one of the following error codes is returned:
Method Write(data As %String) As %Status
This method writes data to the client.
Method EndServer() As %Status
This method gracefully ends the WebSocket server by closing the connection with the client.
Method OpenServer(WebSocketID As %String = "") As %Status
This method opens an existing WebSocket Server. Only a WebSocket operating asynchronously (SharedConnection=1) can be accessed using this method.
WebSocket Properties
The following properties are provided:
SharedConnection (default: 0)
This property determines whether the communication between the client and WebSocket server should be over a dedicated Web Gateway connection or asynchronous over a pool of shared Web Gateway connections. This property must be set in the OnPreServer() method and may be set as follows:
WebSocketID
This property represents the unique identity of the WebSocket.
SessionId
This property represents the hosting CSP Session ID against which the WebSocket was created.
BinaryData
This property instructs the Web Gateway to bypass functionality that would otherwise interpret the transmitted data stream as UTF-8 encoded text and set the appropriate binary data fields in the WebSocket frame header.
This should be set to 1 before writing a stream of binary data to the client. For example:
Set ..BinaryData = 1
WebSockets Server Example
The following simple WebSocket server class accepts an incoming connection from a client and simply echos back data received.
The timeout is set to 10 seconds and each time the Read() method times-out a message is written the client. This illustrates one of the key concepts underpinning WebSockets: initiating a message exchange with the client from the server.
Finally, the WebSocket closes gracefully if the client (i.e. user) sends the string exit.
Method OnPreServer() As %Status
{
   Quit $$$OK
}

Method Server() As %Status
{
   Set timeout=10
   For  {
      Set len=32656
      Set data=..Read(.len, .status, timeout)
      If $$$ISERR(status) {
                          If $$$GETERRORCODE(status) = $$$CSPWebSocketClosed {
                                        Quit
                          }
         If $$$GETERRORCODE(status) = $$$CSPWebSocketTimeout {
               Set status=..Write(“Server timed-out at “_$Horolog)
         }
      }
      else {
         If data="exit" Quit
         Set status=..Write(data)
      }
   }
   Set status=..EndServer()
   Quit $$$OK
}

Method OnPostServer() As %Status
{
   Quit $$$OK
}
WebSockets Server Asynchronous Operation
The example given in the previous section illustrates a WebSocket server operating synchronously with the client over a dedicated InterSystems IRIS connection. When such a connection is established it is labeled as WebSocket in the status column of the Web Gateways Systems Status form. With this mode, the WebSocket is operating within the security context of the hosting web session and all properties associated with that session can be easily accessed.
With the asynchronous mode of operation (SharedConnection=1), the hosting connection is released as soon as the WebSocket Object is created and subsequent dialogue with the client is over the pool of shared connections: messages from the client arrive via the conventional pool of Web Gateway connections to InterSystems IRIS and messages to the client are dispatched over the pool of Server connections that have been established between the Web Gateway and InterSystems IRIS.
In asynchronous mode, the WebSocket Server becomes detached from the main web session: the SessionId property holds the value of the hosting Session ID but an instance of the session object is not automatically created.
The example given previously can be run asynchronously simply by setting the SharedConnection property in the OnPreServer() method. However, it is not necessary to have an InterSystems IRIS process permanently associated with the WebSocket. The Server() method can exit (and the hosting process halt) without closing the WebSocket. Provided the WebSocketID has been retained, the WebSocket can be subsequently opened in a different InterSystems IRIS process and communication with the client resumed.
Example:
Class MyApp.MyWebSocketServer Extends %CSP.WebSocket
{
    Method OnPreServer() As %Status
    {
        MYAPP.SAVE(..WebSocketID)
        Set ..SharedConnection = 1
        Quit $$$OK
    }

    Method Server() As %Status
    {
        Quit $$$OK
    }

    Method OnPostServer() As %Status
    {
        Quit $$$OK
    }
}
Note that the WebSocketID is retained for subsequent use in the OnPreServer() method. Note also, the setting of the SharedConnection property in the OnPreServer() method and that the Server() method simply exits.
Subsequently retrieving the WebSocketID:
Set WebSocketID = MYAPP.RETRIEVE()
Re-establishing a link with the client:
Set ws=##class(%CSP.WebSocketTest).%New()
Set %status = ws.OpenServer(WebSocketID)
Reading from and writing to the client:
Set %status=ws.Write(message)
Set data=ws.Read(.len, .%status, timeout)
Finally, closing the WebSocket from the server side:
Set %status=ws.EndServer()


Previous section           Next section
Send us comments on this page
View this book as PDF   |  Download all PDFs
Copyright © 1997-2019 InterSystems Corporation, Cambridge, MA
Content Date/Time: 2019-09-18 06:45:48