Send socket.io response data to client from node.js server in gzip format

11,123

Solution 1

After reading some of the comments I decided to look at 3rd party libraries to handle the decompression on the client side which led me to JSXCompressor.

http://jsxgraph.uni-bayreuth.de/wp/jsxcompressor/

JSXCompressor will take the base64 encoded gzipped data from the server and handle the decompressing and decoding. Simply download the library and put it in the appropriate folder.

On the server side I'm using zlib to handle the gzipping.

var express = require('express'),
    http    = require('http')
    zlib    = require('zlib');

var app     = express(),
    server  = http.createServer(app),
    io      = require('socket.io').listen(server);

app.use(express.logger('dev'));
app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res) {
    res.send(
    "<script src='/socket.io/socket.io.js'></script>\n"+
    "<script src='/java/jsxcompressor.min.js'></script>\n"+
    "<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>\n"+
    "<script>\n"+
    "var socket=io.connect('http://127.0.0.1:3000');\n"+
    "socket.on('message', function(data) {\n"+
    "   var jsonData = JXG.decompress(data);"+
    "   $(\"h1\").text(jsonData);\n"+
    "});\n"+
    "</script>\n"+
    "<h1></h1>\n"
    );
});

server.listen('3000');

io.sockets.on('connection', function(webSocket) {
    function whileLoop() {
        setTimeout(function() {
                var epoch = (new Date).getTime();
                var jsonData = "{\"result\":"+epoch+"}";
                zlib.gzip(jsonData, function(err, buffer) {
                    webSocket.send(buffer.toString('base64'));
                });
            whileLoop();
        }, 1000);
    }
    whileLoop();
});

Solution 2

The browser client gzip option enables gzip compression for the socket.io script that's served from /socket.io/socket.io.js. It does not affect the actual WebSocket connection.

The WebSocket protocol itself only recently added support for compression of data sent over the socket. Soket.io does not yet support compression, nor do other node WebSocket servers.

To be honest, with the small amount of data you're sending in your example, compression will actually be counter-productive as it's likely to increase the amount of data sent over the wire.

Solution 3

Supported in socket.io 1.4 Compression is enabled by default.

Solution 4

Compression is now enabled by default (>1.4), see also this post for reference: http://socket.io/blog/socket-io-1-4-0/

Share:
11,123

Related videos on Youtube

Brad.Smith
Author by

Brad.Smith

Updated on September 15, 2022

Comments

  • Brad.Smith
    Brad.Smith over 1 year

    The issue I'm having is that I don't know how to be able to tell whether or not the data that I'm sending back to the client is compressed in gzip format. Looking at the output of my server from the command line I'm seeing:

    debug - websocket writing 3:::{"result":1368673052397}
    debug - websocket writing 3:::{"result":1368673053399}
    ...
    

    To me this looks like the server is writing the response in ascii form rather than compressing it first before sending.

    Below is the example I've written to produce these results. From what I've read as long as I set 'browser client gzip' my responses should be getting sent gzipped. If they're not how do I do this and if I am how can I tell from the server's debug info that they are in fact compressed responses.

    When I launch the server I use the following command in BASH:

    $ NODE_ENV=production node app.js

    var express = require('express'),
        http    = require('http');
    
    var app     = express(),
        server  = http.createServer(app),
        io      = require('socket.io').listen(server);
    
    io.configure('production', function() {
        io.enable('browser client minification');
        io.enable('browser client etag');
        io.enable('browser client gzip');
        io.set('log level', 3);
    });
    
    app.use(express.logger('dev'));
    
    app.get('/', function(req, res) {
        res.send(
        "<script src='/socket.io/socket.io.js'></script>\n"+
        "<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>\n"+
        "<script>\n"+
        "var socket=io.connect('http://127.0.0.1:3000');\n"+
        "socket.on('message', function(data) {\n"+
        "   $(\"h2\").text(data);\n"+
        "});\n"+
        "</script>\n"+
        "<h1>"+process.env.NODE_ENV+"</h1>\n"+
        "<h2></h2>\n"
        );
    });
    
    server.listen('3000');
    
    io.sockets.on('connection', function(webSocket) {
        function whileLoop() {
            setTimeout(function() {
                    var epoch = (new Date).getTime();
                    var jsonData = "{\"result\":"+epoch+"}";
                    webSocket.send(jsonData);
                whileLoop();
            }, 1000);
        }
        whileLoop();
    });
    
  • Brad.Smith
    Brad.Smith almost 11 years
    In this example yes, its not necessary. This however is only an example. In my actual application I'm sending back a much longer json string and compression is needed due to bandwidth limitations.
  • josh3736
    josh3736 almost 11 years
    @BradSmith: Unfortunately, you're SOL for now since socket.io doesn't support WebSocket compression. As a workaround, you could send a "data available" message over the socket and then do a traditional XHR request to get the actual JSON data, which could be gzipped.
  • robertklep
    robertklep almost 11 years
    Or use a client/server-compatible compression lib to (de)compress the data yourself.