WebSocket support in XP controller [beta]

Hi.

I have now committed an incubating/beta feature to support websockets in a controller. It can change without notice so use at your own risk right now. To use this feature you will need the latest 6.4.0-SNAPSHOT (2015-02-04T14:00:00 or above). Only service-controllers has this feature so pages/parts cannot implement server-side websocket handling.

To use websocket support, firstly add lib-websocket to your build.

dependencies {
  ...
  include 'com.enonic.xp:lib-websocket:6.4.0-SNAPSHOT'
  ...
}

Next, create a service controller and implement a get method. This method is called first when a websocket http-upgrade request is submitted.

exports.get = function(req) {

   if (!req.webSocket) {
     // Do something if this is not a web-socket request
   }

   // If web-socket request, then you will need to accept the web-socket.
   return {
     webSocket: {
       subProtocols: ['text'],
       data: {
         myField: 'myValue'
       }
     }
   };

}

Sub-protocols indicate what type of sub-protocols to accept. The data field is extra data that is passed to the web-socket session so it can be used later. It only supports simple key/value pairs since it’s serialized between calling threads.

Next is to create the actual web-socket event handling. To do this, implement and export a new method called webSocketEvent.

exports.webSocketEvent = function(event) {

  if (event.type == 'open') {
    // Do something on open
  } else if (event.type == 'close') {
    // Do something on close
  } else if (event.type == 'error') { 
    // Do something on error
  } else if (event.type == 'message') {
    // Do something on message
  }

}

The event object holds the following values:

  • type - type of event (open, close, error and message)
  • session - websocket session information.
  • session.id - websocket session id.
  • session.params - URL parameters from the request.
  • session.path - Path for the websocket endpoint.
  • data - Data that was passed from the get function.
  • error - Error information if type = error.
  • message - Message if type = message.
  • closeReason - Close reason code if type = close.

To send messages to a single web-socket or a group of sockets, you can use lib-websocket. Here’s an example of a chat.

webSocketLib = requlre('/lib/xp/websocket');

exports.webSocketEvent = function(event) {

  if (event.type == 'open') {
    webSocketLib.addToGroup('chat', event.session.id);
    webSocketLib.send(event.session.id, 'You have joined the chat.');
  }

  if (event.type == 'message') {
    webSocketLib.sendToGroup('chat', event.message);
  }

}

If you want to look at a similar example, go to https://github.com/enonic/app-features/tree/master/src/main/resources/site/services/chat. Also, look at the lib-websocket js-docs here: http://repo.enonic.com/public/com/enonic/xp/docs/6.4.0-SNAPSHOT/docs-6.4.0-SNAPSHOT-libdoc.zip!/index.html.

3 Likes

Great! Looking forward to creating chats, newsfeeds, etc. in XP now! :smile:

Awesome!
One question: Is there some kind of timeout here? Will I get a close event and handle that somehow?

I forgot about timeout. We will add the posibility to configure timeout. If timeout occurs, then the client has to re-connect.

This is in 6.5. Closing the topic.