cogAllows you to create WebSocket enabled Applications in XWiki
TypeJAR
CategoryApplication
Developed by

XWiki Development Team

Active Installs68
Rating
Rate!
2 Votes
LicenseGNU Lesser General Public License 2.1
Installable with the Extension Manager

Description

https://raw.githubusercontent.com/xwiki-labs/xwiki-labs-logo/master/projects/xwikilabs/xwikilabsproject.png

Allows you to create WebSocket enabled Applications in XWiki.

How it works

You create a component in XWiki which implements WebSocketHandler and you use @Named to specify a name for it, then when a client connects to the XWiki WebSocket passing the name of your component as the path, your component will be called.

Example

A simple example is the EchoWebSocketHandler which simply replies to each WebSocket message with the same message. Because the EchoWebSocketHandler is named echo, WebSockets directed to the /echo path will reach this handler.

@Component
@Named("echo")
public class EchoWebSocketHandler implements WebSocketHandler
{
   public void onWebSocketConnect(WebSocket sock)
   {
        sock.onMessage(new WebSocket.Callback() {
           public void call(WebSocket sock)
           {
                String msg = sock.recv();
                sock.send(msg);
           }
       });
   }
}

Accessing the handler

To get a WebSocket URL for accessing the echo server, simply use the provided ScriptService in Velocity as follows:

{{velocity}}
{{html clean=false}}
<script>
    // this is a valid WebSocket URL
    var WEBSOCKET_URL = "$services.websocket.getURL('echo')";
</script>
{{/html}}
{{/velocity}}

Then to open a socket to this URL, use the WebSocket API in the browser as normal.

var ws = new WebSocket(WEBSOCKET_URL);
ws.onopen = function () {
    console.log("Websocket Opened");
    ws.send("Hello World!");
};
ws.onmessage = function (msg) {
    console.log(msg.data);
   if (msg.data === 'Hello World!') {
        console.log("Yay it worked!");
    }
};

Read the code of the EchoWebSocketHandler for yourself.

Configuration

The websocket integration exposes 3 new configuration parameters which you can specify in your xwiki.properties file.

  • websocket.bindTo The interface to bind the websocket to, by default this is the undefined interface 0.0.0.0.
  • websocket.externalPath The path which the client should use to reach the websocket, this is needed only if the server's internal hostname is different from the hostname which is visible from the clients or if there is a reverse proxy through which the websocket must tunnel. This parameter includes the protocol, hostname, port (if applicable) and any path on top of that which is supplied by the websocket infrastructure itself, for example: ws://my.external.hostname/xwiki-websocket/
    or via ssl wss://my.external.hostname/xwiki-websocket/ 
  • websocket.port (default: 8093) The number of the port to bind for the websocket, note you will need to make an exception in your firewall for allowing clients to access this port directly on the XWiki server but since the WebSocket infrastructure does not respond to a client unless they provide a key (which is only accessible from the HTTP server), unauthorized users will still be blocked.
  • websocket.ssl.enable (default: false) If set to true, the websocket will be in SSL mode.
  • websocket.ssl.certChainFile The path to file containing an Apache/OpenSSL format X509 certificate chain which will be used for the SSL connection. If this is not set and websocket.ssl.enable is true, a self-signed certificate will be generated at runtime.
  • websocket.ssl.pkcs8PrivateKeyFile The path to a file containing a private key in PKCS #8 format. This is required if websocket.ssl.certChainFile is set.

Setting up an SSL WebSocket

If your wiki uses HTTPS secure mode, most web browsers will require you to use WSS (SSL WebSocket) too. You do not need to use the same certificate for the websocket as you use for the browser, providing websocket.externalPath is set to a different domain (cross-domain websocket connections are supported).

  • Step 1: Create the certificate and private key as you would for setting up Apache or any other popular web browser.
  • Step 2: Place your certificate chain and private key files on the wiki server.
  • Step 3: If necessary, convert the SSLea formatted private key to PKCS #8 format.
  • Step 4: in xwiki.properties, add the following lines:
websocket.ssl.enable=true
websocket.ssl.certChainFile=/the/path/to/your/certificate_chain.pem
websocket.ssl.pkcs8PrivateKeyFile=/the/path/to/your/pkcs8_private.key

Then restart your wiki.

Converting a private key to PKCS #8 format

PKCS #8 formatted keys always begin with a line saying -----BEGIN PRIVATE KEY-----. OpenSSL by default uses the SSLea private key format, keys in this format begin with something like -----BEGIN RSA PRIVATE KEY-----. Unfortunately the SSL WebSocket infrastructure cannot handle this form so you must do a conversion.

You can easily check the type of key without printing the entire thing onto the screen using the following command:

grep 'BEGIN ' ./server.key

To convert your key from SSLea format to PKCS #8, you can use openssl with the following command:

openssl pkcs8 -topk8 -nocrypt -out /path/to/ssl/server_pkcs8.key -in /path/to/ssl/server.key

Testing WebSocket

Using curl you can verify that your WebSocket is working but you will first need an authorization token.
To get the token, login as a user on your wiki and use the following code:

{{velocity}}$services.websocket.getURL('echo'){{/velocity}}

This will return something like wss://my.wiki:8093/xwiki/echo?k=TCOjn9k6i3gILvrjCjt5.

For SSL WebSockets, the request and response should look something like the following:

$ curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: my.wiki" -H "Origin: http://my.wiki:8080/" https://my.wiki:8093/xwiki/echo?k=TCOjn9k6i3gILvrjCjt5
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://my.wiki:8080/
WebSocket-Location: wss://my.wiki/

You may add --insecure to ignore errors due to a self-signed certificate or give the certificate file's path in parameters of curl with --cacert option.

For non SSL websockets, the URL at the end of the command is http instead of https. Since curl is not capable of speaking WebSocket language natively, you will not be able to send proper WebSocket frames to the echo server, it will just hang at the command line, showing that it works.

You can check that the SSL certificates are in order using OpenSSL's s_client function.

openssl s_client -connect my.wiki:8093

Issues on a particular machine

If one particular computer (or even one browser) is not able to connect to an SSL websocket, the cause might be incorrectly configured certificates, to test this take the problematic web browser and navigate to the websocket URL using normal HTTPS (for example https://my.server:8093/) then examine the https certificate and connection for issues. You can also use https://whatsmychaincert.com/ to make sure you have the correct certificate chain configured.

Getting help and reporting issues

Though this extension is not an officially supported part of XWiki, you can get help through the community mailing lists and on the IRC chat channel. Bugs can be reported on https://jira.xwiki.org/browse/WEBSOCKET

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager). Note that installing Extensions when being offline is currently not supported and you'd need to use some complex manual method.

You can also use the manual method which involves dropping the JAR file and all its dependencies into the WEB-INF/lib folder and restarting XWiki.

Release Notes

v1.3

  • Switched from Nettosphere to Netty WebSocket infrastructure
  • Added support for SSL WebSockets
Tags:
Created by Caleb James DeLisle on 2014/01/15 12:41
    

Get Connected