英文:
Cannot set headers after they are sent to the client
问题
Here is the translated code portion:
我的代码中出现了错误。我尝试使用jsonwebtoken生成令牌,但最终出现了错误“Cannot set headers after they are sent to the client”。
以下是详细的错误日志:
```none
throw er; // 未处理的 'error' 事件
^
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'
}
我尝试在注册和登录网站时使用jsonwebtoken包生成用户令牌。
以下是auth文件的代码,其中创建了登录和注册方法:
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
});
// 创建令牌
const email = req.body.email;
const token = jwt.sign(
{ user_id: newUser._id, email },
process.env.TOKEN_KEY,
{
expiresIn: "2h",
}
);
// 保存用户令牌
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: "请填写必填字段"});
}
User.findOne({email: newUser.email}, function (err, userExist) {
if(err){
console.log(err);
res.status(500).json({error: "注册失败"});
}else{
if(userExist){
return res.status(422).json({error: "电子邮件已存在"});
}else{
newUser.save();
res.status(201).json({message: "用户成功注册"});
}
}
});
});
});
// 登录路由
router.post("/signin", (req, res)=>{
if(!req.body.email || !req.body.password){
return res.status(400).json({error: "请填写必要的数据"});
}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: "登录成功"})
}else{
res.json({message: "密码错误"});
}
});
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: "用户未找到"});
};
}
})
})
}
});
module.exports = router;
这是数据库模式和模型的代码:
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;
请注意,我只提供了代码的翻译,没有回答与翻译无关的问题。
英文:
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;
答案1
得分: 2
请注意,无论何时发送响应,都不代表执行结束,HTTP每个请求只有一个响应。因此,为了停止函数的执行,您总是需要使用return
。
您的代码中有一些问题:
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: "请填写必填字段" });
}
在您的signin
路由中发生了相同的问题:
bcrypt.compare(req.body.password, foundUser.password, function (err, result) {
if (result) {
res.json({ message: "成功登录" })
} else {
res.json({ message: "密码不正确" });
}
});
...
res.status(200).json(foundUser);
英文:
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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论