javascript - 如何在node.js express中的路由结束()之后停止中间件序列

标签 javascript node.js express middleware

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

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


主要有三个中间件:

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

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


这就是我得到的输出 GET/login 路由:

 login:  1515262934656  
 session:  1515262935709  
 validation:  1515262935709 

  • 问题是,当用户尝试登录时,他确实登录了,并且路由 POST/login 关闭了响应重定向到 GET/main 页面并将 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);
    }
});

session .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",{}))

关于javascript - 如何在node.js express中的路由结束()之后停止中间件序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48130775/

相关文章:

javascript - 使用 webpack 在浏览器中使用 require 模块

javascript - 将 360 jQuery 轮限制为 300

node.js - 模式更改后如何从 mongo 中获取旧记录

javascript - 显示具有在线编辑能力的文档

javascript - Node 本地主机不返回日期

javascript - 如何生成解析服务器应用程序的文档

javascript - Amcharts Serial - 将多个ajax数据加载为dataprovider

javascript - 在节点之间绘制连接而不重叠节点的算法

javascript - AngularJS/Rails 回形针文件上传

node.js - npm install 不在 GitHub 上安装最新版本