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