Home > Net >  Use middlewares conditionally - Cannot set headers after they are sent to the client
Use middlewares conditionally - Cannot set headers after they are sent to the client

Time:07-10

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:

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?

CodePudding user response:

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');
});
  • Related