How to connect unbuffered data from STDOUT to ServerResponse?

How can I pass unbuffered output from a child process to HTTP.ServerResponse?

The following is Node.js code that works 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 result 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 above code only works if ping successful.

I am using Node.js v0.8.19.

+4
source share
2 answers

This is a common problem , which is not necessarily limited to Node.js.

If you are using Unix, you can use the unbuffer script, which is part of Expect . Most GNU systems also provide stdbuf , which allows you to do the same (although I admittedly am not very familiar with it).

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

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

If you work in Windows, everything is quite complicated, since Windows does not provide any PTY equivalent. Projects such as winpty (and its JavaScript binding, pty.js ) will try to recreate this functionality using the Windows console APIs , although I found that their implementation is somewhat distorted and incomplete.

ActiveState win32 Expect package is not the easiest thing to install and does not include the unbuffer script in the default distribution. However, if you manage to complete all the steps and make a few small changes to the Unix unbuffer script, you must compile the unbuffer , which you can then call from Node.

+5
source

You kill the ping process on request, which ends as soon as the request is successfully received on the server. ping continues to close before it can print 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 continues forever, so you cannot wait for it to end. Use -c to ping x the number of times.

0
source

All Articles