Home > Back-end >  Cannot set headers after they are sent to the client
Cannot set headers after they are sent to the client

Time:01-04

What is error in my code? I had tried to generate tokens using jsonwebtoken but ended up having a error "Cannot set headers after they are sent to the client". This is detailed log of error:

throw er; // Unhandled 'error' event
      ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:393:5)
    at ServerResponse.setHeader (node:_http_outgoing:644:11)
    at ServerResponse.header (D:\web dev\projects\Mern-Project\server\node_modules\express\lib\response.js:794:10)
    at ServerResponse.send (D:\web dev\projects\Mern-Project\server\node_modules\express\lib\response.js:174:12)
    at ServerResponse.json (D:\web dev\projects\Mern-Project\server\node_modules\express\lib\response.js:278:15)
    at D:\web dev\projects\Mern-Project\server\router\auth.js:45:34
    at D:\web dev\projects\Mern-Project\server\node_modules\mongoose\lib\model.js:5228:18
    at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
Emitted 'error' event on Function instance at:
    at D:\web dev\projects\Mern-Project\server\node_modules\mongoose\lib\model.js:5230:15
    at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

I tried to generate the token for user while registering and sign- in website by using jsonwebtoken package. Here is code of auth file where is created login and sign-in methods

const express = require("express");
const { default: mongoose } = require("mongoose");
const router = express.Router();
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
require("../db/conn");
const User = require("../model/userSchema");
router.get("/", (req, res)=>{
    res.send("Hello world to server router js");

});

router.post("/register", (req, res)=>{
  bcrypt.hash(req.body.password, 12, function (err, hash) { 
    const newUser = new User({
      name:req.body.name,
      email: req.body.email,
      phone: req.body.phone,
      work: req.body.work,
      password: hash
      
    });
    // Create token
    const email = req.body.email;
    const token = jwt.sign(
      { user_id: newUser._id, email },
      process.env.TOKEN_KEY,
      {
        expiresIn: "2h",
      }
    );
    // save user token
    newUser.token = token;
    res.status(201).json(newUser);

    if(!newUser.name || !newUser.email || !newUser.phone || ! newUser.work || !newUser.password){
      return res.status(422).json({error: "Plz fill the required field"});
    }
    User.findOne({email: newUser.email}, function (err, userExist) { 
      if(err){
        console.log(err);
        res.status(500).json({error: "failed to register"});
      }else{
        if(userExist){
          return res.status(422).json({error: "Email already Exist"});
        }else{
          newUser.save();
          res.status(201).json({message: "user registered succesfully"});
        }
      }
     });

   });
  });

  //LOgin route
  router.post("/signin", (req, res)=>{
    if(!req.body.email || !req.body.password){
      return res.status(400).json({error: "Plz fill the required data"});
   }else{
    bcrypt.hash(req.body.password, 12, function (err, hash) { 
      User.findOne({email: req.body.email}, function (err, foundUser) {
        if(err){
          console.log(err);
        }else{
          if(foundUser){
            bcrypt.compare(req.body.password, foundUser.password, function (err, result) {
                  if(result){
                    res.json({message: "successfully log in"})
                  }else{
                    res.json({message: "incorrect password"});
                  }
              });
              const email = req.body.email;
              const token = jwt.sign(
                { user_id: foundUser._id, email },
                process.env.TOKEN_KEY,
                {
                  expiresIn: "2h",
                }
              );
              foundUser.token = token;
              res.status(200).json(foundUser);
          }else{
            res.status(400).json({message: "user not found"});
          };
        }
      })
    })
  }
  });

module.exports = router;

This is code to database schema and model:

const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
    name:{
        type:String,
        required:true
    },
    email:{
        type:String,
        required:true
    },
    phone:{
        type:Number,
        required:true
    },
    work:{
        type:String,
        required:true
    },
    password:{
        type:String,
        required:true
    },
    tokens:[
         { token:{
            type:String,
            required:true
         }

    }]

});

const User = mongoose.model("User", userSchema);

module.exports = User;

CodePudding user response:

Please pay attention whenever you send a response, it doesn't mean that the execution ends, and also the HTTP has just only one response per request. Hence, to stop the execution of a function you always need to put return.

There are some parts in your code, which makes trouble:

newUser.token = token;
res.status(201).json(newUser);

Here you must decide whether to send the client or continue checking the database.

Because a few lines after, you have this condition, which might send the client another response:

if(!newUser.name || !newUser.email || !newUser.phone || ! newUser.work || !newUser.password){
  return res.status(422).json({error: "Plz fill the required field"});
}

The same issue happened in your signin route:

bcrypt.compare(req.body.password, foundUser.password, function (err, result) {
  if(result){
    res.json({message: "successfully log in"})
  }else{
    res.json({message: "incorrect password"});
  }
});
...
res.status(200).json(foundUser);
  • Related