Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Reliable minimalistic WebSocket client (uses Adobe Flash where native WebSocket is not available)

branch: master
as update
lib update
public readme update
.gitignore fixed readme and added the swf
.npmignore initial commit
LICENSE initial commit
README.md readme update
build.sh initial commit
config.xml initial commit
optjs.sh update
package.json update
README.md

ws-flash-client: gimite's WebSocket Flash client shim adapted as Connect middleware for easy usage in Node.js' Express framework, to be used with einaros' ws WebSocket server

Important

For increased reliability, it is suggested to use the WebSocket protocol over encrypted connections only. Some proxy servers handle the unencrypted form of the protocol in a way which prevents it from operation. This is being addressed by "masking" in newer versions of the protocol, however too many older versions are already in the wild. See the second code example on the ws-rpc project page on how to configure HTTPS support in your Node.

Why

  • 99% of WebSocket use cases currently can be covered with just 2 transports: the WebSocket itself, or Adobe Flash client talking through the WebSocket protocol.

  • socket.io, the Node.js' most prominent WebSocket framework supporting multiple transports, has currently about ~160 open issues and ~600 closed issues, suggesting that the problem area it tries to solve may be scoped too wide. (Just supporting all the WebSocket protocol flavors is a big undertaking, now add cross-browser support for multiple alternative transports and a lot of framework functionality on top of that = easily a very complex project.)

Except

The only two areas which could probably use an additional bidirectional transport type:

  • some Android browsers without Adobe Flash (see the support here and here), however those users still have a choice to install an alternative browser, e.g. Firefox Mobile, or the Chrome for Android which is currently in beta, and get the native WebSocket support.
  • iOS versions older than 4.2 (released on 10/2010), however these seem to make up less than 10% of all iOS versions in use.

Also

On the desktop on IE and Opera without Flash installed (~0.1% of users), the following is available:

  • IE9 and lower can install Google Frame. IE10 due in Q3/2012 will support WebSocket.
  • Opera 11 users can enable WebSocket by pasting "opera:config#Enable%20WebSockets" into the address bar, pressing ENTER and changing the setting.

Thus

Perhaps having lean and mean pure-WebSocket server (with good WebSocket protocol versions support) and making sure the client can use one of the WebSocket protocols to talk to it (natively or with the help of Adobe Flash), just may be the way to go these Wild-West days.

Briefly Tested On

  • Google Chrome 17 Mac, 16, 17 Win
  • Firefox 7 Mac, 10 Win
  • Internet Explorer 6, 7, 8, 9 on Win XP and Win 7 (Flash)
  • Safari 5.1 Win, 5 Mac
  • Opera 9.8 Win (Flash)
  • Chrome Beta on Android 4.0, Galaxy Nexus
  • Mobile Safari on iOS 5.0.1, iPhone 3GS

Usage

On command line:

npm install express
npm install ws
npm install ws-flash-client
npm install policyfile

In your main script.js:

var prod = process.env.NODE_ENV === 'production';
var app = require('express').createServer();
var wss = new (require('ws').Server)({ server: app });
var wsflash = require('ws-flash-client');
require('policyfile').createServer().listen(prod ? 843 : 10843, app);

app.configure(function() {

    // configure other stuff like express globals, jade, stylus, etc.
    // ...

    // configure the ws-flash-client middleware:
    // (you can also serve the files yourself from __dirname + /node_modules/ws-flash-client/public)
    app.use(wsflash.middleware(express));

    // static file handling must come afterwards:
    app.use(express.static(pub));

    app.listen(prod ? 80 : 1234);

    // example action for your websocket server:
    wss.on('connection', function(ws) {
        ws.send(JSON.stringify({ msg: 'hello world' }));
    });

});

In your HTML page (JADE syntax shown):

!!! 5
html
    head
        meta(http-equiv='X-UA-Compatible', content='IE=Edge,chrome=1')
        //if lt IE 8
            script(src='//cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.min.js')
        script(src='//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js')
        script(src='/ws-flash.min.js')
        script(src='/myclientcode.js')
    body
        #msg

In your clientcode.js:

$(function() {

    $.wsFlashClientInit({}, function(err) {

        if(err)
            return $('#msg').text('no websocket for old men');


        // and off you go:

        var ws = new window.WebSocket('ws://' + window.location.host + '/');

        ws.onmessage = function(e) {
            $('#msg').text(JSON.parse(e.data).msg);
        };

    });

});

Note: the necessity of callback is a bit ugly, but thanks to it, the browsers with native WebSocket support only see about 800 bytes of overhead in 1 request (instead of loading the full shim code plus swfobject.js on each request, which is about 22kB in 2 requests, so even if cached it's still an overhead for us minimalists). To clarify, it's possible to load the scripts synchronously, but only from the same domain, and for the purpose of this library (while not using Ender), and also in general sense of lean web apps, it's good to have the option of the CDN-hosted scripts. (Huh.)

Additional options for $.wsFlashClientInit(options, callback):

{
    chromeFrameFallback: true,
        // In the IE, if both the native WebSocket and Adobe Flash are missing, offer to install Chrome Frame.

    forceFlash: false,
        // Force the use of the Flash shim even if native WebSocket is available.

    swfLocation: '/ws-flash-client.swf',
        // Overridable location of the Flash SWF file.

    policyFile: null,
        // Allows to specify an alternate Flash policy file location.
        // See: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/Security.html#loadPolicyFile(%29

    crossDomainInsecureSupport: false,
        // calls Security.allowDomain("*") and Security.allowInsecureDomain("*") in the Flash file
        // See: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/Security.html#allowDomain(%29
        // See: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/Security.html#allowInsecureDomain(%29

    debug: false,
        // Make the Flash say things.

    logger: { log: function(msg) {}, error: function(msg) {} },
        // Overridable logger, defaults to console.log and console.error, if available, or to empty functions if not.

    swfobjectUrl: 'http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js'
        // Where to load swfobject.js from.
}

//TODO

  • Testing! (Not much time for this though. Fill Issues, send Pull Requests.)
  • Add Ender support.

See Also

  • ws-rpc - lightweight RPC support for ws

License

New BSD License.

Something went wrong with that request. Please try again.