PLui PLui - 1 month ago 5
Node.js Question

Node.js serving HTML, execute command line and callback function

I wanted to use Node.js to serve up one HTML file and respond to a call on the same port. When it serves the HTML page, I also want it to run a command locally to display the output of the command. I can't seem to get the output. It keeps erroring out. I'm pretty sure I'm missing something fundamental but not sure what. Here is the code snippet:

var os = require("os");
var hostname = os.hostname();
var exec = require('child_process').exec;

var http = require('http'),
fs = require('fs');
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(req, res) {
if(req.url.includes("callback")) {
//do stuff
} else {
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(html);
res.write("<BR><BR>NodeJS Server:"+hostname);
var exec = require('child_process').exec;
var cmd = 'uname -a | awk \'\{print $2\}\'';
exec(cmd, function(error, stdout, stderr) {
res.write("<BR><BR>uname output: "+ stdout);
});
res.end();
}
}).listen(80);
});


Here's the error I got:

events.js:160
throw er; // Unhandled 'error' event
^

Error: write after end
at ServerResponse.OutgoingMessage.write (_http_outgoing.js:439:15)
at /tmp/web-serve-one-port2.js:111:15
at ChildProcess.exithandler (child_process.js:197:7)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:191:7)
at maybeClose (internal/child_process.js:877:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)


Thanks!

Answer

You're calling end() before you do the last write, as exec() is asynchronous.

Here's basically what happening

exec(cmd, function(error, stdout, stderr) {
    res.write("<BR><BR>uname output: "+ stdout); // this happens last
});

res.end(); // this happens first

And you can write after the response has ended. Change your code to :

var os = require("os");
var hostname = os.hostname();
var exec = require('child_process').exec;

var http = require('http'),
    fs = require('fs');

fs.readFile('./index.html', function(err, html) {
    if (err) {
        throw err;
    }

    http.createServer(function(req, res) {
        if (req.url.includes("callback")) {
            //do stuff
        } else {
            var cmd = 'uname -a | awk \'\{print $2\}\'';
            exec(cmd, function(error, stdout, stderr) {
                res.writeHeader(200, { "Content-Type": "text/html" });
                res.write(html);
                res.write("<BR><BR>NodeJS Server:" + hostname);
                res.write("<BR><BR>uname output: " + stdout);
                res.end();
            });

        }
    }).listen(80);
});
Comments