Notification modes

Notifications are sent using two modes: raw data and a JavaScript callback function.

Clients can decide at run time which method to use depending on which client-side technique is used to receive and process the push notifications.

Raw data

Notifications are written directly to the output stream of the HTTP response in the following format: notification-length:notification. Subsequent notifications are appended to the output stream.

This mode is intended to be used by the XMLHttpRequest (XHR) JavaScript object on the client side. The XHR object does not have access to the raw output stream of the response and can see the entire server output only by examining the responseText property. The recommended approach for querying responseText is to query periodically for new data to keep track of what was already read and to ensure that only new data is read on each iteration.

Note: The XHR cannot follow cross-domain redirects. To avoid this limitation, when a client sends the initial request to the push server to register for push notifications, the push server outputs the redirect URL in its response instead of performing an HTTP redirect to the push redirector. It is the responsibility of the client to send the second request to the push redirector URL.

The example below shows client-side code that uses the raw data notification mode.

<html>
  <head>
    <script type="text/javascript">
      // Initial offset to skip dummy data needed b/c of IE bug.
      var lastPos = 256; 
      var xhr;
      
      if (typeof XDomainRequest != "undefined") // IE
      {
        xhr = new XDomainRequest();
      }
      else // Non IE
      {
        xhr = new XMLHttpRequest();
      }

      function load()
      {
        xhr.open("get", "push", true);
        xhr.send(null);

        /* 
         * The output of the Push Server is the URL to the Push 
         * Redirector (manual redirect) to avoid cross domain issues.
         */
        xhr.open("get", xhr.responseText, true);
        xhr.send(null);
        setInterval(poll, 100);
      }
      
      function poll()
      {
         var res = xhr.responseText.substring(lastPos);
         var pos = 0;   
         var len = "";
         
         while (res.charCodeAt(pos) > 47 && res.charCodeAt(pos) < 58)
         {
           len += res.charAt(pos++);
         }
         
         var readLen = parseInt(len) + len.length + 1;
         
         if (res.length >= readLen)
         {
           lastPos += readLen;
           document.getElementById('content').innerHTML =
             res.substring(len.length + 1, readLen);
         }
      }
    </script>
  </head>
  <body onload="load()"><div id="content"/></body>
</html>

JavaScript callback function

The client specifies a JavaScript callback function in a URL parameter when establishing the initial Comet connection. The function must have a single parameter.

Notifications are written to the output stream of the HTTP response as the invocation of the JavaScript function with the notification as the parameter passed to the function:
<script type='text/javascript'<function>('<notification>');</script>

This mode is intended to be used in an IFrame so that the server output is rendered directly by the browser and the function is executed on demand as the output is rendered. The function can use the notification passed to it to set other fields on the page, including fields in a different IFrame or in the parent document.

Note: Because of cross-domain security restrictions, both the IFrame accessing the push server or push redirector and the parent where the IFrame is declared must share a common ancestor domain. The document.domain variable must also be set to the common ancestor domain in the IFrame’s parent.
The example below shows client-side code that uses the JavaScript callback function mode.
<html>
  <head>
    <script type="text/javascript">
      // Allow access to cross-domain URLs with a common ancestor domain
      document.domain="<common-domain>";

      function update(value)
      {
        document.getElementById('content').innerHTML = value;
      }
    </script>
  </head>
  <body>
    <div id="content"/>
    <iframe src="push" frameborder="0/>
  </body>
</html>