How to pipe unbuffered data from STDOUT to ServerResponse?

How can I pipe the unbuffered output from the child process to HTTP.ServerResponse?

The Node.js code below does work for buffered output, but not for unbuffered output.

var http = require('http'),
    spawn = require('child_process').spawn;

http.createServer(function (req, res) {
    req.on('data', function (data) {
        var ping = spawn("ping", ["127.0.0.1"]);
        ping.stdout.pipe(res);
        ping.stderr.pipe(res);
        req.connection.on('end', function() {
            ping.kill();
        });
    });
});

Here is the output from ping 127.0.0.1:

ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1

Since ping writes request timeouts to STDOUT as unbuffered data, the code above only works if ping is successful.

I'm using Node.js v0.8.19.

This is a common problem that isn't necessarily limited to Node.js.

If you're on Unix, you could use the unbuffer script, which is part of Expect. Most GNU systems also provide stdbuf, which lets you do the same thing (although I'm admittedly not very familiar with it).

If you want to use unbuffer, you just need to change your above example to:

var ping = spawn("unbuffer", ["ping", "127.0.0.1"]);

If you're on Windows, things are quite a bit more difficult, as Windows does not natively provide any sort of equivalent to a PTY. Projects such as winpty (and its JavaScript binding, pty.js) attempt to re-create this functionality using the Windows Console API, although I've found their implementation to be somewhat buggy and incomplete.

ActiveState's win32 Expect package isn't the easiest thing to install, and doesn't include the unbuffer script in the default distribution. However, if you manage to get everything working and make a few small modifications to the Unix unbuffer script, you should be able to compile an unbuffer executable, which you can then call from Node.

You are killing the ping process on request connection end which happens as soon as request is recieved successfully on server. ping keeps closing before it can output Request timeout for icmp_seq 5.

Try to do something like this

var http=require('http');
var spawn = require('child_process').spawn;
http.createServer(function (req, res) {
        var ping = spawn("ping", ["127.0.0.1","-c","20"]);
        ping.stdout.pipe(res);
        ping.stderr.pipe(res);
}).listen(8080);

Note: ping goes on forever so you cannot wait for it to end. Use -c to ping x number of times.