4

I would like to have custome response time-out, so that I am trying to send the response from setTimeout callback if the processing time exceeds certain interval.

In the following example, I set 20ms as time-out period within which services.getReport() has to be processed otherwise the API has to send response as response_timed_out.

The following code works fine but it throws exception like

Cannot set headers after they are sent to the client

router.post("/getReport", (req, res) => {
  setTimeout(() => {
    res.send({ status:503, msg: "response_timed_out" });
  }, 20);
  services.getReport(req, res);
});
SuperStar518
  • 2,814
  • 2
  • 20
  • 35
Prem
  • 5,685
  • 15
  • 52
  • 95
  • 1
    Is services.getReport calling `res.writeHead(...)` or calling res.send? Check this post for the _Cannot set headers after they are sent to the client_ https://stackoverflow.com/questions/7042340/error-cant-set-headers-after-they-are-sent-to-the-client – Martín Zaragoza Jun 24 '19 at 12:43
  • 1
    you could use `if (res.headersSent) { return; }` or clear the timeout. – Roland Starke Jun 24 '19 at 12:44

1 Answers1

3

You can use setTimeout method on the request object to define timeout time for each route.

router.post("/getReport", (req, res) => {
  req.setTimeout(2000);
  services.getReport(req, res);
});

You can also define timeout time globally for all routes on the server.

const server = app.listen(port, () => {});
server.setTimeout(15000);

You can also provide the second argument which is callback that will run when timeout occurs. If you want the callback then you call setTimeout on the response.

router.post("/getReport", (req, res) => {
  res.setTimeout(2000, () => res.send('timed_out'));
  services.getReport(req, res);
});
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
  • This looks good. Is it possible to read the value `req.setTimeout`, which is `2000` in this case, within the `services.getReport` function so that I can check as follows `if (req.timeout >= 2000) res.send('timed_out')` – Prem Jun 24 '19 at 13:06
  • The updated one gives error as `net::ERR_EMPTY_RESPONSE` – Prem Jun 24 '19 at 13:27
  • @Prem It seems that callback is not called if you call it on request but it should work if you call it on response instead. – Nenad Vracar Jun 24 '19 at 13:51
  • The updated one works fine. The only additional thing I have added is `if (!res.headersSent) { res.send(report) }` within `services.getReport` function – Prem Jun 24 '19 at 14:05
  • @Prem Shouldn't that throw an error because you can only send headers once? – Nenad Vracar Jun 24 '19 at 14:07
  • 1
    Its `!res.headersSent`. I have updated the same in my comment. Thank you – Prem Jun 24 '19 at 14:09