在我执行以下操作后出现Cannot set headers after they are sent to the client
错误:1.登录,2.注销,然后3.登录。
我的困惑源于:1.我什至看不到代码在'login'
post
路由中设置标头的位置,以及2. '/login'
中的命令序列似乎发生错误的post
路线与'/signup'
post
路线中的路线相同,后者的执行没有问题。也就是说,两者都分配给req.session.user
,然后分配给res.redirect('/protected_page');
var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var multer = require('multer');
var upload = multer();
var app = express();
app.set('view engine', 'pug');
app.set('views', __dirname + '/views');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(upload.array());
app.use(cookieParser());
app.use(session({secret: "Shh, it's a secret!"}));
app.use(express.static('public'));
var users = [];
app.get('/signup', function(req, res){
res.render('signup');
});
app.post('/signup', function(req, res){
if(!req.body.id || !req.body.password) {
res.status(400);
res.send("Invalid details!");
} else {
users.filter(function(user) {
if (user.id === req.body.id) {
res.render('signup', {
message: "User Already Exists! Login or choose another user id"});
}
});
var newUser = {id: req.body.id, password: req.body.password};
users.push(newUser);
req.session.user = newUser;
res.redirect('/protected_page');
}
});
function checkSignIn(req,res, next){
if (req.session.user) {
next();
} else {
var err = new Error("Not logged in!");
next(err);
}
}
app.get('/protected_page', checkSignIn, function(req, res){
res.render('protected_page',{id: req.session.user.id});
})
app.get('/login', function(req,res){
res.render('login');
})
app.post('/login', function(req,res){
if (!req.body.id || !req.body.password) {
res.render('login', {message: "Please enter both id and password!"});
} else {
users.filter(function(user){
if (user.id === req.body.id && user.password === req.body.password) {
req.session.user = user; //*** PROBLEM SEEMS TO BE HERE ***
res.redirect('/protected_page'); //*** OR HERE ***
}
});
res.render('login', {message: "Invalid credentials"});
}
})
app.get('/logout', function(req, res){
req.session.destroy(function(){
console.log("user logged out")
});
res.redirect('/login');
})
app.use('/protected_page', function(err,req,res,next){
console.log(err);
res.redirect('/login');
});
我看到其他人也提出了类似的问题,但是这些情况似乎都不适用于我的情况,因为在其他情况下,我可以看到代码在发送响应后尝试在标头中写入内容,但是在我的情况下,不知道发生了什么。在此先感谢您,如果有人可以提供帮助!
答案 0 :(得分:2)
如果您仔细查看自己的/login
路线,则有以下几行:
users.filter(function(user){
if (user.id === req.body.id && user.password === req.body.password) {
req.session.user = user; //*** PROBLEM SEEMS TO BE HERE ***
res.redirect('/protected_page'); //*** OR HERE ***
}
});
res.render('login', {message: "Invalid credentials"});
正如您已经确定的那样,问题出在if
语句的两行之一中,而您是对的:问题出在第二行(带有redirect
的那一行)。
其原因是:重定向设置了location
标头,状态代码(301
,302
或307
),并将其发送到客户端并关闭连接。不幸的是,您没有在这里退出功能,因为这里没有return
之类的东西。
这意味着继续执行,并且对res.render
的调用发生,该调用试图设置一些标题并呈现一个页面-由于连接已关闭,该页面不起作用。取决于异步的东西,它也可能以相反的方式发生(我没有足够仔细地跟进来检查哪个先出现)。但是,这是您出现问题的根源:您尝试运行res.render
和res.redirect
,并且都设置了标头,并且都关闭了连接。
除此之外,您正在以一种奇怪的方式使用数组的filter
函数,因为它返回了,所以您应该这样做:
if (!req.body.id || !req.body.password) {
res.render('login', {message: "Please enter both id and password!"});
return;
}
const isLoginCorrect = users.some(function (user) {
return user.id === req.body.id && user.password === req.body.password;
});
if (isLoginCorrect) {
req.session.user = user;
res.redirect('/protected_page');
return;
}
res.render('login', {message: "Invalid credentials"});
由于您实际上对过滤后的用户列表并不感兴趣,因此最好使用some
,它仅返回true
或false
,具体取决于是否在与给定谓词函数匹配的数组中找到了item。然后,您可以检查此布尔值,并确定如何继续。
答案 1 :(得分:1)
错误在于条件逻辑中。如果满足以下条件
if (user.id === req.body.id && user.password === req.body.password)
都被满足,两行
res.redirect('/protected_page');
和
res.render('login', {message: "Invalid credentials"});
将被执行,发送后将再次设置响应头。
简单的解决方案:-设置else条件。
if (user.id === req.body.id && user.password === req.body.password) {
req.session.user = user; //*** PROBLEM SEEMS TO BE HERE ***
res.redirect('/protected_page'); //*** OR HERE ***
}
else {
res.render('login', {message: "Invalid credentials"});
}
注意:-您的注册代码也有此问题。尝试在下一个请求中发送相同的user.id。
答案 2 :(得分:0)
尝试以下代码:
var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var multer = require('multer');
var upload = multer();
var app = express();
app.set('view engine', 'pug');
app.set('views', __dirname + '/views');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(upload.array());
app.use(cookieParser());
app.use(session({secret: "Shh, it's a secret!"}));
app.use(express.static('public'));
var users = [
{
id : "1",
password : "1"
}
];
app.get('/signup', function(req, res){
res.render('signup');
});
app.post('/signup', function(req, res){
if(!req.body.id || !req.body.password) {
res.status(400);
res.send("Invalid details!");
} else {
users.filter(function(user) {
if (user.id === req.body.id) {
res.render('signup', {
message: "User Already Exists! Login or choose another user id"});
}
});
var newUser = {id: req.body.id, password: req.body.password};
users.push(newUser);
req.session.user = newUser;
res.redirect('/protected_page');
}
});
function checkSignIn(req,res, next){
if (req.session.user) {
next();
} else {
var err = new Error("Not logged in!");
next(err);
}
}
app.get('/protected_page', checkSignIn, function(req, res){
res.render('protected_page',{id: req.session.user.id});
})
app.get('/login', function(req,res){
res.render('login');
})
app.post('/login', function(req,res){
if (!req.body.id || !req.body.password) {
res.render('login', {message: "Please enter both id and password!"});
} else {
users.filter(function(user){
if (user.id === req.body.id && user.password === req.body.password) {
req.session.user = user; //*** PROBLEM SEEMS TO BE HERE ***
res.redirect('/protected_page'); //*** OR HERE ***
}
else {
res.render('login', {message: "Invalid credentials"});
}
});
}
})
app.get('/logout', function(req, res){
req.session.destroy(function(){
console.log("user logged out")
});
res.redirect('/login');
})
app.use('/protected_page', function(err,req,res,next){
console.log(err);
res.redirect('/login');
});