【问题标题】:app.get() being called multiple times expressapp.get() 被多次调用 express
【发布时间】:2018-08-04 06:08:27
【问题描述】:

我对@9​​87654325@ 还很陌生,正在尝试创建一个简单的网站,该网站首先要求身份验证,然后将用户重定向到一个页面。

所以,我要做的是创建一个中间件来监听对我的网站发出的每个请求。

这个中间件的作用是检查用户是否登录我的网站,如果没有,则重定向到请求的页面,然后重定向到登录页面,这是我的代码。

var express = require('express');
var app = express();

// middleware for using static files 
app.use('/public', express.static(__dirname + '/public')); // all the js files for check_before.html
app.use('/templates', express.static(__dirname + '/templates')); // here are css/js files for login.html 

// setting up views folder
app.set('views', __dirname + '/views'); // check_before.html is sitting here
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

app.use((req, res, next) => {
    res.render('check_before.html'); 
// here in the html I implement the logic using js files which are located in public folder.

    next();

});

// if not logged in , the user gets here
app.get('/login', (req, res, next) => {

    res.render('login.html')

});

// if logged in redirect to some page 
app.get('/welcome_page', (req, res) => {
    return 'welcome'

});

一切都很顺利,直到用户点击http://localhost:8000/login 页面(在检查他们是否已登录之后)页面会继续加载多次并且不会停止重新加载。 我已经在模板文件夹中定义了login.html页面的所有css、js文件,该文件夹通过引用这个问题在中间件上方加载 Express middleware getting called many times。这会是个问题吗?

这可能是什么原因?

这是我在控制台中遇到的错误。

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

有什么猜测吗?

编辑1
我经历了这个问题Error: Can't set headers after they are sent to the client,我猜它得出的结论是明确设置标题可能有问题。

这可能是一个原因吗?因为在我的逻辑中,如果用户未登录,我只是使用window.location.replace('http://localhost:8000/login') 将用户重定向到login 页面。 我应该使用其他方法进行重定向吗?

编辑2

有人建议我必须编写一个中间件来检查用户是否经过身份验证,并为此获得一种标志,但正如我上面所说的,我正在实现check_before.html(客户端)。所以无法使用它。

【问题讨论】:

  • 来自 expressjs.com 文档 - expressjs.com/en/4x/api.html#res.render - 尝试使用 res.render('index', function(err, html) { res.send(html); });。 PS - res.send() 将添加 res.end() 以关闭与客户端的连接
  • @Deryck 错误仍然存​​在,我已经用错误代码更新了我的问题
  • 这可能是因为app.use 中的res.render() 就在app.get('/login' ... 之前。您可能需要在模板中简单地包含 check_before 文件,而不是尝试在此处呈现它
  • @Deryck 我再次更新了我的问题,而且我应该使用什么来代替渲染?如果我不使用渲染,那么中间件将如何响应?它怎么会知道它(check_before.html)位于那里..
  • 如果check_before 严格用于检查用户是否登录,请参见github.com/expressjs/session

标签: javascript node.js express routes middleware


【解决方案1】:

我有两个猜测:

  1. 您不应在 res.render 之后调用 send(或任何其他函数)。

  2. 验证用户登录的中间件应该是这样的(仅适用于您要验证用户的路由)

中间件应该是这样的

const isAuthenticated = (req, res, next) => {
    if(req.isAuthenticated()) {
        next();
    } else {
        res.redirect('/');
    }
}    

app.get('/welcome_page', isAuthenticated, (req, res) => {
  return 'welcome'

});

【讨论】:

  • 请原谅我,但我无法得到它。 req.isAuthenticated() 是什么意思?这是否意味着我应该在那里实现逻辑?
  • 我实际使用的是window.location.replace('http://localhost:8000/login') 是用户已登录。
  • 如果您使用 express-session 和 passport 等中间件,它会在登录后的每个请求中添加该方法。如果您不使用护照,您可以使用 express-session 并在登录后调用 req.login() 方法,该方法将使用用户对象向请求中添加一个 cookie,因此如果用户已登录,则请求对象也将具有一个用户对象(如果(req.user)//然后它的身份验证。)
  • Cannot set headers after they are sent to the client 是因为你在 res.render 之后调用了其他方法,你不应该这样做
  • 所以就像登录后我创建一个cookie并检查每次用户使用任何url的请求/
【解决方案2】:

原因是在您的/login 请求之前调用了中间件。要修复它,您需要修改中间件功能。它应该是这样的:

app.use((req, res, next) => {
    if(isLoggedIn) {  //isLoggedIn is a flag that checks whetehr user is logged-in or not
        res.render('check_before.html');
    } else {
        // here in the html I implement the logic using js files which are located in public folder.

        next();
    }
});

【讨论】:

  • 我猜你还没有阅读编辑的问题,实际上我在客户端实现了逻辑,这意味着我不能在服务器端使用标志..
  • 最好在客户端和服务器端都进行验证
猜你喜欢
  • 2016-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-04
  • 1970-01-01
相关资源
最近更新 更多