Home > Blockchain >  node.js cannot set headers after they are sent to the client error
node.js cannot set headers after they are sent to the client error

Time:08-16

i have this simple middleware that is generating the problem, usually i get this error when i try to send a response after a response was already sent ..but here this is not the case and i can't understand why is this happening.. my code works as follows: use a middleware to extract the current user from a jwt cookie and store it in res.locals variable, if no user exists then null would be stored, then move to next which is the main controller, from there i make a db query and try to send it as response and that's where the error happens..i can confirm that the issue originates in the extraction middleware as the controller worked fine when i removed the mw function..this is my code

middleware


function extractUser(req, res, next) {
    let token = req.cookies.userToken;
    if (!token) {
        res.locals.user = null;
        next();
    }
    try {
        let { id } = jwt.verify(token, SERVER_SECRET);
        if (id) {
            User.findById(id).then(user => {
                res.locals.user = user;
                next();
            })
        } else {
            res.locals.user = null;
            next();
        }
    } catch (err) {
        res.locals.user = null;
        next();
    }
}

controller

router.get("/:id", extractUser, (req, res) => {
    let productId = req.params.id;
    Product.findByIdAndUpdate(productId, { $inc: { views: 1 } }, { new: true })
        .populate("thing", "thing thing thing thing -_id")
        .populate({ path: "thing", populate: { path: "thing", select: "thing thing thing thing thing -_id" } })
        .exec().then(product => {
            console.log(product);
            res.status(200).json({ product });
        }).catch(err => {
            console.log(err);
            res.sendStatus(400);
        })
})

CodePudding user response:

Can you please try once with the following code in your controller?

router.get("/:id", extractUser, async (req, res) => {
  try{ 
        let productId = req.params.id;
        const product = await Product.findByIdAndUpdate(productId, { $inc: { views: 1 } }, { new: true })
            .populate("thing", "thing thing thing thing -_id")
            .populate({ path: "thing", populate: { path: "thing", select: "thing thing thing thing thing -_id" } });
       
        return res.status(200).json({ product });
  }catch (err) {
     console.log(err);
     return res.sendStatus(400);
  }
})

CodePudding user response:

as stated in the question i found that issue originated in the user extraction middleware..after some research i found that next() function wouldn't break/return control from its function and that i was calling next multiple times which would break everything..as a solution make sure next() would be called only once or just use return next() to return from the function.

fixed MW code


function extractUser(req, res, next) {
    let token = req.cookies.userToken;
    if (!token) {
        res.locals.user = null;
        next();
    }else{
try {
        let { id } = jwt.verify(token, SERVER_SECRET);
        if (id) {
            User.findById(id).then(user => {
                res.locals.user = user;
                next();
            })
        } else {
            res.locals.user = null;
            next();
        }
    } catch (err) {
        res.locals.user = null;
        next();
    }
}
}

  • Related