Node.js [ERR_HTTP_HEADERS_SENT]:在Express中将头发送到客户端后,无法设置头

Node.js [ERR_HTTP_HEADERS_SENT]:在Express中将头发送到客户端后,无法设置头,node.js,express,cookies,Node.js,Express,Cookies,我发送的曲奇http://localhost:5000/users/register ,未设置到的标题中http://localhost:5000/users/register. 我可以访问正文中的cookie,但不能访问标题中的cookie 我的App.js代码是 require("dotenv").config(); const express = require("express"); const mongoose = require("m

我发送的曲奇http://localhost:5000/users/register ,未设置到的标题中http://localhost:5000/users/register. 我可以访问正文中的cookie,但不能访问标题中的cookie

我的App.js代码是

require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const fileUpload = require("express-fileupload");
const cookieParser = require("cookie-parser");
const users = require("./routers/users");

const app = express();
app.use(express.json());
app.use(cookieParser());
app.use(cors());
app.use(
  fileUpload({
    useTempFiles: true,
  })
);

// connecting to MongoDB
const mongoURL = process.env.MONGO_URL;

mongoose
  .connect(mongoURL, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
  })
  .then(() => console.log("DataBase has been connected !"))
  .catch((err) => console.log("Cannot connect to database", err.message));

// routes
app.use("/users", users);

const port = process.env.PORT || 5000;
app.listen(port, () => {
  console.log(`I am listening at ${port}`);
});

我的路由器代码


const express = require("express");
const bcrypt = require("bcrypt");
const { Users, userSchema } = require("../models/user");
const jwt = require("jsonwebtoken");

const router = express.Router();

// registering
router.post("/register", async (req, res) => {
  try {
    const { name, email, password } = req.body;
    console.log(name, email, password);
    //console.log(Users);
    //console.log(userSchema);
    let user = await Users.findOne({ email });
    if (user) return res.status(404).json({ msg: "The email already exists" });

    if (password.length < 6)
      return res.status(404).json({ msg: "The password is less than 6" });

    // Hashing password
    const newPassword = await bcrypt.hash(password, 10);

    // creating a user and saving in db
    user = await new Users({ name, email, password: newPassword });
    await user.save();

    // creating JWT token for authenticating the user
    const accessToken = createAccessToken({ id: user._id });
    const refreshToken = createRefreshToken({ id: user._id });


// Cookie is being sent in the headers to the listed "path"
    res.cookie("refreshToken", refreshToken, {
      httpOnly: true,
      path: "/users/refreshtoken",
    });

    res.json({ accessToken });
    //return res.json({ password, newPassword, user, accessToken, refreshToken });
  } catch (err) {
    return res.status(500).json({ msg: err.message });
  }
});

router.get("/refreshtoken", (req, res) => {
  try {
    const rfToken = req.cookies.refreshToken;
    if (!rfToken)
      return res.status(400).json({ msg: "Please login or sign up" });

    // verifying the token that we sent when user registered
    // the token shows ig it's the registered user or not
    jwt.verify(rfToken, process.env.REFRESH_TOKEN, (error, decoded) => {
      if (error)
        return res.status(400).json({ msg: "Please login or sign up" });
      console.log(decoded);
      const accessToken = createAccessToken({ id: decoded.id });
      res.json({ decoded, accessToken });
    });

    res.json({ msg: "DS", rfToken });
  } catch (error) {
    return res.status(500).json({ msg: error.message });
  }
});

const createAccessToken = (userID) => {
  return jwt.sign(userID, process.env.ACCESS_TOKEN, { expiresIn: "1d" });
};

const createRefreshToken = (userID) => {
  return jwt.sign(userID, process.env.REFRESH_TOKEN, { expiresIn: "7d" });
};
module.exports = router;


const express=要求(“express”);
常量bcrypt=要求(“bcrypt”);
const{Users,userSchema}=require(“../models/user”);
const jwt=require(“jsonwebtoken”);
const router=express.router();
//登记
路由器.post(“/register”),异步(req,res)=>{
试一试{
const{name,email,password}=req.body;
控制台日志(名称、电子邮件、密码);
//console.log(用户);
//log(userSchema);
let user=wait Users.findOne({email});
if(user)返回res.status(404.json)({msg:“电子邮件已经存在”});
如果(密码长度<6)
返回res.status(404.json)({msg:“密码小于6”});
//散列密码
const newPassword=wait bcrypt.hash(密码,10);
//创建用户并保存在数据库中
user=等待新用户({名称、电子邮件、密码:newPassword});
等待user.save();
//创建用于验证用户的JWT令牌
const accessToken=createAccessToken({id:user.\u id});
const refreshttoken=createrefreshttoken({id:user.\u id});
//Cookie正在标题中发送到列出的“路径”
res.cookie(“refreshToken”),refreshToken{
httpOnly:true,
路径:“/users/refreshtoken”,
});
res.json({accessToken});
//返回res.json({password,newPassword,user,accessToken,refreshtToken});
}捕捉(错误){
返回res.status(500).json({msg:err.message});
}
});
路由器.get(“/refreshtoken)”,(请求,res)=>{
试一试{
const rfToken=req.cookies.refreshToken;
如果(!rfToken)
返回res.status(400.json)({msg:“请登录或注册”});
//验证用户注册时我们发送的令牌
//令牌显示它是否是注册用户
jwt.verify(rfToken,process.env.REFRESH_TOKEN,(错误,解码)=>{
如果(错误)
返回res.status(400.json)({msg:“请登录或注册”});
控制台日志(已解码);
const accessToken=createAccessToken({id:decoded.id});
res.json({decoded,accessToken});
});
res.json({msg:“DS”,rfToken});
}捕获(错误){
返回res.status(500).json({msg:error.message});
}
});
const createAccessToken=(userID)=>{
返回jwt.sign(userID,process.env.ACCESS_令牌,{expiresIn:“1d”});
};
const createRefreshToken=(userID)=>{
返回jwt.sign(userID,process.env.REFRESH_令牌,{expiresIn:“7d”});
};
module.exports=路由器;

Cookie未设置为“/users/refreshtoken”的标头,它是在正文中发送的,我可以在“/users/refreshtoken”的正文中看到Cookie,但在标头中看不到。我不知道为什么。

此错误通常是由不正确的异步排序引起的,这会导致您有一个或多个代码路径,可以尝试向同一传入请求发送多个响应

我在您的
路由器.get(“/refreshtoken”,…)
路由处理程序中看到了一个这样的例子。此问题可能发生的一个地方是此处的标记处:

router.get("/refreshtoken", (req, res) => {
  try {
    const rfToken = req.cookies.refreshToken;
    if (!rfToken)
      return res.status(400).json({ msg: "Please login or sign up" });

    // verifying the token that we sent when user registered
    // the token shows ig it's the registered user or not
    jwt.verify(rfToken, process.env.REFRESH_TOKEN, (error, decoded) => {
      if (error)
        return res.status(400).json({ msg: "Please login or sign up" });
      console.log(decoded);
      const accessToken = createAccessToken({ id: decoded.id });
=====>
      res.json({ decoded, accessToken });
=====>
    });

=====>
    res.json({ msg: "DS", rfToken });
=====>

  } catch (error) {
    return res.status(500).json({ msg: error.message });
  }
});
此代码将启动异步非阻塞
jwt.verify()
函数,然后立即执行:

    res.json({ msg: "DS", rfToken });
然后,一段时间后,它将执行以下任一操作:

return res.status(400).json({ msg: "Please login or sign up" });

两者都将尝试发送第二个响应。在我看来,这条路线中的代码有三种可能的结果:

  • 没有代币
  • 令牌存在,但无效
  • 令牌存在且有效
  • 这意味着您应该有三个不重叠的响应。但是,您有四个发送响应的位置,它们重叠,导致重复响应。我不知道你为什么会有
    res.json({msg:“DS”,rfToken})代码行,因为只要存在令牌(无论有效还是无效),它总是运行。你需要解决这个问题。可能您应该完全删除这一行代码,或者在
    jwt.verify()
    回调中用这一行代码替换另一个响应

    const accessToken = createAccessToken({ id: decoded.id });