写入Cookie时发送标题后无法设置标题

时间:2018-08-24 14:05:06

标签: node.js express cookies runtime-error

这是一个通过检查登录页面中注册的输入是否存在于数据库中而起作用的代码。一切正常。但是,当我想设置一个cookie(我只是想随机设置它,以便查看它是否起作用)以便将其状态保存为在线状态时,发生了错误

Cannot set Headers after they are sent

我从中了解到这是因为我是在相同的请求或类似的请求下执行res.renderres.cookies的,但是,我删除了res.render并保留了res.cookies,错误消失了,但即便如此,它也没有注册任何cookie(开发工具的网络面板上没有cookie,也没有在控制台上写入document.cookie

我还试图在渲染页面时将该代码移至请求的get位置,但仍然无法正常工作。

这是服务器代码:

// Importing modules/packages
let connection = require("./Connection.js");
let bodyParser = require("body-parser");
var cookieParser = require("cookie-parser");
let express = require("express");
let app = express();
app.use(cookieParser());
let urlencodedParser = bodyParser.urlencoded({ extended: false });

// Server and routing
app.listen(3000, function() {
  console.log("The server at port 3000 is open!");
});
app.set("view engine", "ejs");
app.get("/Signup", (req, res) => {
  res.render("Register");
});
app.get("/", function(req, res) {
  res.redirect("Login");
});
app.get("/Login", function(req, res) {
  res.render("Login");
});

// Database's Connection
connection.connect(err => {
  if (err) {
    throw "ERROR! " + err;
  }
  console.log("Has connected to MySQL Database!");
});

// Requesting and Receiving Data from body parser
app.post("/Signup", urlencodedParser, function(req, res) {
  console.log(req.body);
  res.render("Register");
  connection.query(
    `insert into users (Username, User_Password, Email_Address) values ("${
      req.body.Username
    }", ${req.body.Password}, "${req.body.Email}")`,
    function(err) {
      if (err) throw "An error has happened while excuting the query " + err;
      console.log("Query got excuted successfully!");
    }
  );
});

app.post("/Login", urlencodedParser, (req, res) => {
  connection.query(
    `SELECT Username FROM users WHERE User_Password = ${
      req.body.Password
    } AND Username = "${req.body.Username}"`,
    function(err, results) {
      if (results.length === 0) {
        console.log(
          "Sorry, this username/password doesn't exist in our database."
        );
      } else {
        console.log("Logined successfully!");
        res.cookie("Friend", "Jack");
      }
    }
  );
  res.render("Login");
});

我也尝试使用req.cookie("Friend")来读取cookie,但是没有用。我不知道怎么了。

请问该如何解决?

1 个答案:

答案 0 :(得分:1)

您要在回调中设置cookie,但要在回调之外进行渲染,应该像这样:

app.post("/Login", urlencodedParser, (req, res) => {
  connection.query(
    `SELECT Username FROM users WHERE User_Password = ${
      req.body.Password
    } AND Username = "${req.body.Username}"`,
    function(err, results) {
      if (results.length === 0) {
        console.log(
          "Sorry, this username/password doesn't exist in our database."
        );
      } else {
        console.log("Logined successfully!");
        res.cookie("Friend", "Jack");
      }
      res.render("Login"); // <-- moved here
    }
  );
});

Node.js中的代码通常不按顺序执行-这是由于异步特性(我写了关于here的更多内容)。

app.post("/path", (req, res) => {
  // 1
  connection.query(query, () => {
    // 3 after query has been executed
    res.cookie("Friend", "Jack");
  });
  // 2
  res.render("Login");
});

在您的代码中执行如下:

  1. connection.query已执行,但是给定回调,其余代码不会等待query完成,而是转到下一条语句
  2. res.render("Login");,它将结果呈现给浏览器
  3. 该查询最终被执行,结果返回到我们尝试设置res.cookie的回调中-此时将失败。

还要注意您的代码原样包含SQL injection vulnerabilities。您应该在部署到生产之前修复这些问题!