2016年8月26日 星期五

Streaming http response

Streaming http response

某些時候,我們會希望在Server端執行比較久的回應結果可以持續得回傳回來。在express中,可以透過res.write()來持續回傳結果,直到回傳完成,再結束這個連線... 下面是express中的片段範例... 其中"/exec"這個route是在本地端執行child_process.exec(),然後將結果回傳...

範例

app.use('/exec', function(req, res){
  exec(function(d, t){
    res.write(d);
    if(t && t == 'end') res.end('\ndone...');
  });
});

function exec(fn){
  const spawn = require('child_process').spawn;
  const ls = spawn('bash', ['/tmp/test.sh']);
  ls.stdout.on('data', (data) => {
      fn(`stdout: ${data}`, 'stdo-data');
  });

  ls.stderr.on('data', (data) => {
      fn(`stderr: ${data}`, 'stde-data');
  });

  ls.on('close', (code) => {
      fn(`child process exited with code ${code}`, 'end');
  });
}
下面是express所欲執行的shell...
# File: /tmp/test.sh
echo 1
sleep 1

echo 2
sleep 2

echo 3
sleep 3
啟動Server後,再透過curl測試...
curl localhost:3000/exec
stdout: 1
stdout: 2
stdout: 3
child process exited with code 0
done...
將會發現,上面的執行結果將是一行一行回覆回來,在結束之前connection將不會中斷...

細看執行重點

上面的程式之所以可以block住connection並且一段一段回傳結果,其中重點在express routing中使用res.write()來做data的回傳,另外也因為child_process.spawn()提供event driven的方式,在每筆data回傳時候呼叫對應的event執行方式...