Search code examples
node.jsexpresscookiescookie-httponly

How to fix the "cannot set headers after they are sent to the client" error in node?


I know this question has been asked several times, but the solution provided didn't work for me.

I have a protected route to find a user. The request is validated by an authenticate middleware, which basically checks if the user's cookie is valid, and then the route getUser is called. The route works well when I don't use the middleware, so the issue may come from authenticate.

I have used return res.status(200).json({}) as suggested.

When testing the route with the cookie, chai makes two calls. The first one succeeds, but as soon as the route is hit, another call is made, without any cookie. Weird. In Postman, same thing. It works wonderfully without authenticate, but returns unauthorized with it. In the terminal, the error is:

[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Here is the authenticate middleware and the route:

// router
const router = express.Router();
router.get("/user/:id", authenticate, getUser);

// authenticate
const authenticate = (req: Authenticate, res: Response, next: NextFunction) => {
  const { mycookie } = req.cookies; 
  if (mycookie) {
    jwt.verify(mycookie, process.env.JWT_TOKEN_KEY, (error, parsedToken) => {
      if (error) {
        return res.sendStatus(403);
      }
      req.cookie = { _id: parsedToken._id, locale: parsedToken.locale };
      return next();
    });
  }
  return res.sendStatus(401);
};

export default authenticate;

// the get - user/:id route
const getUser = async (
  req: GetUser,
  res: IResponse
): Promise<IResponse> => {
  try {
    const user = await UserControler.findUserById(req.params.id);
    return res.status(200).json({ user });
  } catch (err) {
    throw new Error("error.unknown");
  }
};

export default getUser;

How to fix this?


Solution

  • In your authenticate functions, you forgot to add an else statement to if (mycookie).

    Unauthorized will therefore always be sent, which is clearly the reason why you get unauthorized with a good cookie, and then as unauthorized as already been sent, the error you describe will be throw when getUser tries to sent the http response.

    Wrap return res.sendStatus(401); in an else statement and it should work fine.