Q:

Express Cannot set headers after they are sent

I have a situation where I am running an interactive C# console-program from node/express. The program runs in an infinite loop, accepts a string from the command-line, and echoes it back.  
The following code works for the first time I call http://localhost:3000?command=hello 
Next time around, Node crashes by reporting Can't set headers after they are sent.
If the move the const script = spawn('/Users/amarshanand/shadowClient/myscript.sh'); in the sendToShell(), it works, but since I have to start a new shell and the script, it takes a lot longer.
How can I make it work like start once and accept command for each request.
const express = require('express')
const app = express()

const { spawn } = require('child_process');
const script = spawn('/Users/amarshanand/shadowClient/myscript.sh');

const sendToShell = (command, done) => {

    script.stdout.on('data', (stdout) => {
        console.log(`stdout: ${stdout}`);
        done(stdout);
    });

    script.stderr.on('data', (stderr) => {
        console.log(`error: ${stderr}`);
    });

    script.stdin.write(`${command}\n`);

}

app.get('/', (req, res) => {
    sendToShell(req.query.command, result => res.send(`${result}`));
})

app.get('/getstate', (req, res) => {
    res.send('state');
})

app.post('/setstate:state', (req, res) => res.send('posted state'));

app.listen(3000, () => console.log('Example app listening on port 3000!'))

A:

That particular error occurs when you try to send more than one response to an incoming request.  When I examine your code, I see that this particular piece of code:
script.stdout.on('data', (stdout) => {
    console.log(`stdout: ${stdout}`);
    done(stdout);
});

Can receive the data event more than once and when it does, it will call done(stdout) more than once which will cause the caller to call res.send() more than once.
With streams, you have no idea how many times the data event will be called.  It could be called only once or it could be called many times with lots of small pieces of data.

In addition, you only have one script that all your requests use.  So, each time you call sendToShell(), you add yet another script.stdout.on('data', ...) event handler so they will pile up and you will have duplicates causing you to call done() more than once for each data event.  If you're going to stick with this structure, then you need a way to know when all the data has been sent for the last command and then you need to remove that event handler so they don't pile up.

FYI, this code also has concurrency issues because multiple requests could come into your server that cause you to run a command and you'd have no idea which response belongs with which command.  If you're going to keep just one shell open, they you probably need to queue commands to the shell so you don't send the next command or set up its event handlers to read the response until the previous command is done.  That way you won't be reading the response from the wrong command.

