如何阻止中间件序列在 node.js express中的路由 end() 之后进行


  • 请帮忙。我不明白是我做错了什么,还是事情是如何解决的。
  • 这只是简单的登录/注册应用程序。我正在使用中间件来防止用户在没有基于 cookie 检查登录的情况下访问/主页。如果没有登录,唯一可用的路由是 GET/POST/login,和 GET/POST/register,在他们的声明变成中间件后,检查用户是否有特殊的 cookie,如果没有,用户将被重定向到 GET/login,它工作得很好。

如果需要,您可以在GitHub上查看整个代码:MNEVO


有三个主要的中间件:

  1. cookieparse(parse cookie from request)
  2. session(对 cookie 进行编码并将其写入 req.cookie.user)
  3. 验证(如果密码是我的,那么你将从 cookie 中获取 JSON,如果不是,它将是未定义的)

我在每个(cookie 解析器除外)和登录路由中插入了控制台.log。


这就是我得到的输出,将要获取/登录路由:

login:  1515262934656  
session:  1515262935709  
validation:  1515262935709 

  • 问题是,当用户尝试登录时,他做到了,并且路由 POST/login 关闭连接,响应重定向到 GET/主页并将 cookie 写入用户,
.post((req,res)=>{
var user = req.body;
//validate input
s2m.login(user , (s2mres)=>{
if(s2mres.statusCode === 200){
res.set("Set-Cookie", `one = ${session.getOneCookie(user)}}; Path='/'`);
res.set("Location", "/main");
res.status(302).end();
}else{
res.set("Location", "/login");
res.status(302).end();
}
});
});
  • 这个中间件仍在尝试继续,并且由于用户首先没有cookie,中间件试图将他重定向到GET/login页面,当然它失败了,因为以前的路由POST/login已经关闭了对客户端的响应。
LOGIN success:  1515264690286
session:  1515264690378
validation:  1515264690379 // Im redirected to register page at this point(I think)
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
at ServerResponse.header (/home/ubuntu/workspace/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/home/ubuntu/workspace/node_modules/express/lib/response.js:170:12)
at app.get (/home/ubuntu/workspace/server/server.js:86:6)
at Layer.handle [as handle_request] (/home/ubuntu/workspace/node_modules/express/lib/router/layer.js:95:5)
at next (/home/ubuntu/workspace/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/ubuntu/workspace/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/ubuntu/workspace/node_modules/express/lib/router/layer.js:95:5)
at /home/ubuntu/workspace/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:335:12)
session:  1515264691190
validation:  1515264691191
  • 问题:在以前的路由已经关闭连接后,有没有办法破坏中间件序列,或者我弄错了,还有其他方法可以工作?

应用

var env = require("./env.js");
var app     = require("express")();
var session = require("./session/session.js");
var cookieparser = require("cookie-parser");
var bp        = require("body-parser");
var setCookie = require("set-cookie");
var pug     =   require("pug");
var s2m = require("./s2m/s2m.js");
const ENVIRONMENT = env.c9;

app.get("/get-login-css", (req,res)=>{
res.sendFile(__dirname+"/client/css/login.css");
});
app.use(bp.urlencoded({ extended: false }));
app.route("/register")
.get((req,res)=>{
res.send(pug.renderFile("./pugs/register.pug",{})).status(200).end();
})
.post((req,res)=>{
var user = req.body;
//validate input
s2m.register(user, (s2mres)=>{
if(s2mres.statusCode === 200){
res.set("Set-Cookie", `one = ${session.getOneCookie(user)}; Path='/'`);
res.set("Location", "/main");
res.status(302).end();
}else{
res.set("Location", "/login?notification=wrong%20login%20or%20password");
res.status(302).end();
}
});
});
app.route("/login") 
.get((req,res)=>{
console.log("login: ",Date.now());
res.end(pug.renderFile("pugs/login.pug" , {notification: req.query.notification}));
})
.post((req,res)=>{
var user = req.body;
//validate input
s2m.login(user , (s2mres)=>{
if(s2mres.statusCode === 200){
res.set("Set-Cookie", `one = ${session.getOneCookie(user)}}; Path='/'`);
res.set("Location", "/main");
res.status(302).end();
}else{
res.set("Location", "/login");
res.status(302).end();
}
});
});
app.get("/logout",(req,res)=>{
res.set("Set-Cookie", `one = ${undefined}; Path='/'`);
res.set("Location", "/login");
res.status(302).end();
});

//YOU SHALL NOT PASS (if you don't have login in your cookies)
app.use(cookieparser());
app.use(session.session());
app.use(session.validate());
//ROUTS
app.get("/view-cookie",(req,res)=>{
console.log("this is bad");
//user is exist if the code get thus far. so what we well do with it ?
var user = req.cookies.user;
//redirect to the home page
res.send(JSON.stringify(user));
});
app.get("/",(req,res)=>{
res.set("Location", "/main");
res.status(302).end();
});
app.get("/main",(req,res)=>{
res.send("<div style='text-align: center'> <h1>WELCOME</h1> <br> <a href='/logout'>LOGOUT</a> </div>");
});

app.listen(ENVIRONMENT.port, (err,port)=>{
if(!err){
console.log("WE ROLLING! on: ", ENVIRONMENT.domain);
}
});

会话.js

var encdec = require("./encdec.js");
var cookie = require("./cookie.js");
var find = function(cipher){
try{
return JSON.parse(encdec.decrypt(cipher));
}catch(err){
return undefined;
}
};
var session = function(callback){
return function(req,res,next){
console.log("session: ",Date.now());
req.cookies.user = find(req.cookies.one);
next();
};
};
var validate = function(callback){
return function(req,res,next){
console.log("validation: ",Date.now());
if(!req.cookies.user){
res.redirect("/register");
// res.status(302).end();
}
next();
}
}
var getOneCookie = function(obj){
return encdec.encrypt(JSON.stringify({array: cookie.wrap(obj)}));
};

module.exports = {
session,
validate,
getOneCookie
};

你以错误的顺序做了一些事情。res.send()在那里发送响应。 任何对该请求执行进一步操作的尝试都将触发您看到的错误。

因此,请更改以下内容:

res.send(pug.renderFile("./pugs/register.pug",{})).status(200).end();

对此:

res.send(pug.renderFile("./pugs/register.pug",{}));

.status(200)是默认值,因此您无需设置它。 而且,res.send()发送请求,因此您不需要.end()之后。

如果您仍然想设置状态,则必须先设置它:

res.status(200).send(pug.renderFile("./pugs/register.pug",{}));

其他一些评论。

您可以替换此类型的序列:

res.set("Location", "/login");
res.status(302).end();

有了这个:

res.redirect("/login");

此外,您应该能够将 pug 直接插入 Express 中的渲染系统,这样您就可以使用它:

res.render("./pugs/register.pug", {})

而不是:

res.send(pug.renderFile("./pugs/register.pug",{}))
  • 这是一个欺骗的时刻。问题只是在字符串行中的单个右大括号中。

    - 但是回答我自己的问题,答案是:


中间件序列随着官方文档中指定的 req\res 周期的终止而自动终止,


无论我是否关闭了重定向的连接,或者结束,或者结束状态,只要我关闭了连接。感谢您的关注。 希望在这一点上它能说服其他人的文档可靠性,这是我对此表示怀疑的。

最新更新