I can’t solve ERR_HTTP_HEADERS_SENT

Asked

Viewed 24 times

-1

My program points ERR_HTTP_HEADERS_SENT which by what I understand, occurs when a response has already been sent by the server. I’m trying to create a controller method of a route that changes some user information. For this I made two other methods of the same controller, one that loads the user and the other authenticates. These two methods come before the method that changes user information, in that order: load -> authenticate -> alters. I don’t see where the ERR_HTTP_HEADERS_SENT comes from, since it points on the only line where a response is sent. I don’t have much experience with express. Here is the code:

controller.loadUser = async (req, res, next) => {
  try {
    await database.sync();
    
    let userId = req.body.data.id;
    
    const user = await User.findByPk(userId);
    
    req.user = user;
  }
  
  catch (error) {
    req.error = error;
  }
  
  finally {
    next();
  }
};

controller.authenticateUser = async (req, res, next) => {
  if (req.error !== undefined)
    next();
  
  try {
    await database.sync();
    
    let {login: authLogin, password: authPassword} = req.body.data.authentication;
    let {login, password} = req.user;
    
    if (login === authLogin && password === authPassword)
      next();
    
    let error = new Error("User authentication failed.");
    error.name = "UserAuthenticationError";
    
    throw error;
  }
  
  catch (error) {
    req.error = error;
  }
  
  finally {
    next();
  }
};

controller.updateUser = async (req, res, next) => {
  if (req.error !== undefined)
    next(req.error);
  
  var user = req.user;
  
  try {
    await database.sync();
    
    let newData = req.body.data.update;
    
    for (let attribute of Object.keys(newData))
      user[attribute] = newData[attribute];
    
    user.save({
      "fields": [
        "username", "login", "password"
      ]
    });
    
    // Aqui é onde o error é apontado.
    res.json({
      "data": user
    });
  }
  
  catch (error) {
    next(error);
  }

};

Here is the mistake:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:370:5)
    at ServerResponse.setHeader (node:_http_outgoing:573:11)
    at ServerResponse.header (/home/moccot/NetBeansProjects/secoar/node_modules/express/lib/response.js:771:10)
    at ServerResponse.send (/home/moccot/NetBeansProjects/secoar/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/home/moccot/NetBeansProjects/secoar/node_modules/express/lib/response.js:267:15)
    at controller.updateUser (/home/moccot/NetBeansProjects/secoar/src/api/controller/users.js:137:9)

1 answer

0

The call of the function next does not terminate the execution of the current function.

Note that in function authenticateUser you have two calls to function next, one if the condition req.error !== undefined is true, and the other if in its finally.

What happens if the condition req.error !== undefined is true, is that the next will be invoked, causing the next middleware/route to be executed, in this case, the updateUser, but after the function updateUser finished running (actually it will not wait to finish because it is asynchronous), the function authenticateUser round again, calling the next again, and therefore running the updateUser again.

Like the updateUser is executed twice, the res.json({ "data": user }) is invoked twice. The first time is no problem, the second time it fails, because you have already sent the answer.

To end the function authenticateUser, and prevent it from continuing to run after the next, use a return:

controller.authenticateUser = async (req, res, next) => {
  if (req.error !== undefined) {
    return next();
  }

  // resto do código
};

Browser other questions tagged

You are not signed in. Login or sign up in order to post.