Search code examples
node.jsstdouthttp-status-codesspawnpdflatex

Why can't I send the response status inside a spawn answer?


In my node Api I use the following function for a specific endpoint in order to create a PDF and return its name:

exports.findOne = (req, res) => {
  .
  .
  .
 const { spawn } = require('child_process');
 const ls = spawn('pdflatex', [name], {cwd: '/path'});

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

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

 res.status(200).send({ message: name.split('.tex')[0] });
};

This works nice but the name of the PDF is returned before the PDF is created. So I changed the function in order to return the name only after the pdf is created:

exports.findOne = (req, res) => {
  .
  .
  .
 const { spawn } = require('child_process');
 const ls = spawn('pdflatex', [name], {cwd: '/path'});

 ls.stdout.on('data', (data) => {
   console.log(`stdout: ${data}`);});
   res.status(200).send({ message: name.split('.tex')[0] });

 ls.stderr.on('data', (data) => {
   console.error(`stderr: ${data}`);
   res.status(401).send({ message: "PDF Err" });
 });
};

I get the error:

stdout: This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex)
restricted \write18 enabled.

_http_outgoing.js:491
throw new Error('Can\'t set headers after they are sent.');
^

Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (/.../response.js:771:10)
at ServerResponse.send (/.../response.js:170:12)
at ServerResponse.json (/.../response.js:267:15)
at ServerResponse.send (/.../response.js:158:21)
at Socket.ls.stdout.on (/....report.controller.js:60:18)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at Pipe.onread (net.js:607:20)

Do you have any ideas how to solve this and to be able to send the answer only after the pdf is created? Thank you!


Solution

  • To send a response after PDF file is generated, you can use the event close in stdout. It will be triggered when the spawn command is done.

    ls.stdout.on('close', () => {...});