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