Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Use middlewares conditionally – Cannot set headers after they are sent to the client

I’m trying to make a POST request where I need to switch between two middlewares based on a req.body parameter. The two middlewares are auth middlewares for customer and merchant respectively. I send a type in request body and its value can be either customer or merchant.

The merchantAuth and customerAuth middlewares are almost alike so I’m only writing one here.
So far I have done this:

router.js:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

router.post('/', async (req, res, next) => {
  try {
    if (req.body.type == 'customer') {
      customerAuth(req, res, next);
    }
    else if (req.body.type == 'merchant') {
      merchantAuth(req, res, next);
    }
    return res.json('done');
  } catch (err) {
    return res.status(500).send('Internal server error. ' + err.message);
  }
});

merchantAuth/customerAuth:

module.exports = function (req, res, next) {
  // Get token from header
  const token = req.header('x-auth-token');
  // Check if no token
  if (!token) {
    return res.status(401).json("Authorization denied");
  }
  // Verify token
  try {
    const decoded = jwt.verify(token, config.jwtAccessSecret);
    if (!decoded.customer) {
      return res.status(401).json("Invalid token");
    }
    req.customer = decoded.customer;
    next();
  } catch (err) {
    return res.status(401).json("Invalid token");
  }
};

The error I get is
Cannot set headers after they are sent to the client
(node:11152) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:558:11)…..
….

I know why I’m getting this error but I don’t know why I’m getting it and how to solve it. If I provide a wrong auth token for a customer, it gives an error on if (!decoded.customer) condition and then returns. However, it continues to execute on the router.js file until return res.json('done'); line where it gives me this error.
Why does the execution on router.js continue when I have already given response?

>Solution :

Your current code executes res.json('done') after calling the authentication middleware so that two responses are sent in case of failed authentication, leading to the observed error. You want to execute res.json('done') only when the authentication middleware calls next():

router.post('/', async (req, res, next) => {
  function nextAfterAuthentication() {
    res.json('done');
  }
  try {
    if (req.body.type == 'customer') {
      customerAuth(req, res, nextAfterAuthentication);
    }
    else if (req.body.type == 'merchant') {
      merchantAuth(req, res, nextAfterAuthentication);
    }
  } catch (err) {
    return res.status(500).send('Internal server error. ' + err.message);
  }
});

Or, equivalently

router.post('/', async (req, res, next) => {
  try {
    if (req.body.type == 'customer') {
      customerAuth(req, res, next);
    }
    else if (req.body.type == 'merchant') {
      merchantAuth(req, res, next);
    }
  } catch (err) {
    return res.status(500).send('Internal server error. ' + err.message);
  }
}, function() {
  res.json('done');
});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading