我在express.js / node.js中编写了一个中间件来检查会话,如果找到了用户ID,则显示用户的菜单,或者是默认菜单。
每个页面请求都会检查一个id并从数据库中获取用户数据(id,name,category等)。
这是中间件:
module.exports = function(req,res,next){
console.log("INSIDE SESSION HANDLER");
if(!req.session.uid) return next();
else{
User.get(uid, function(user){
if (!user) {return next(err);}
else{
req.user = res.locals.user = user;
next();
}
})
}
}
然后,ejs检查当地人,如果有ID,则显示用户的菜单。
我正在加载一个测试页面,我没有使用socket.io库,但忘记删除<script src="/socket.io/socket.io.js"></script>
行。
<!DOCTYPE html>
<html>
<head>
<title><%= title %> , <%= settings.title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="/socket.io/socket.io.js"></script>//<== SHOULD DELETE THIS
<h1>Login</h1>
<%include menu%> //<== USES EJS TO CHECK LOCALS AND SHOW DEFAULT OR USER MENU
</head>
<body>
当script src
行不存在时,中间件执行一次(仅console.log("INSIDE SESSION HANDLER");
只看过一次)。
当script src
行出现时,显然有404错误,但中间件执行了两次(看了console.log("INSIDE SESSION HANDLER");
两次)。
以下是console.log
的输出:
INSIDE SESSION HANDLER
GET / 304 66ms //page
GET /stylesheets/style.css 304 11ms
INSIDE SESSION HANDLER //again
GET /socket.io/socket.io.js 404 28ms - 1.04kb
GET /multimedia/01.jpg 304 4ms //images...
GET /multimedia/02.jpg 304 5ms
我想真正了解请求/响应和中间件。那么为什么会这样呢?为什么这个中间件由于404错误而执行了两次? 404错误响应是否导致中间件执行两次?
由于
修改
我在app.js中使用中间件,如:
app.use(favicon(__dirname + '/node_modules/static-favicon/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({resave:'false', saveUninitialized:'false', secret:'secret'}));
app.use(express.static(path.join(__dirname, 'public')));
app.set('multimedia', __dirname + '/public/multimedia');
app.use(handler); //<= THE MIDDLEWARE IN QUESTION
app.use(messages);
app.get('/', routes.list);
app.get('/register', register.form);
app.post('/register', register.submitit);
答案 0 :(得分:2)
你的中间件运行两次的原因是它为初始请求运行了一次,而对于404(不存在的静态脚本)运行一次。
如果WriteConcern.WMajority
可以找到一个文件,它会发送带有相应文件的响应,如果它找不到正确的文件(就像您的情况那样),它会调用express.static
尝试将请求与其他路由匹配,运行在next()
下面定义的任何其他中间件。
换句话说,如果express.static
确实找到了要提供的文件,那么它下面的中间件将无法运行。在您的情况下,中间件针对实际请求运行一次,并且一旦尝试查找文件或正确的路由作为响应。
通过记录普通静态文件的express.static
和不存在的文件可以观察到这一点:
app.js -
req.path
layout.hbs(渲染&#39; /&#39;) -
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next){
console.log('Requested path: %s', req.path);
next();
})
我们将看到中间件只会记录初始请求和404的请求路径,而不是静态文件。 e.g:
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
<link rel='stylesheet' href='/stylesheets/style.css' /> <!-- exists -->
<link rel='stylesheet' href='/stylesheets/foo.css' /> <!-- doesn't exist -->
</head>
<body>
{{{body}}}
</body>
</html>
希望这有帮助。
答案 1 :(得分:-1)
你在哪里应用这个中间件?
例如,如果你有
app.use(handler)
其中handler
的格式为function (req, res, next)
,它将应用于每个请求(使用任何HTTP谓词)。或者,
app.get('/some/route', handler)
其中handler
适用于/some/route
以下的任何地方(例如/some/route/any/deepness
)。
所以我的猜测是你过度应用中间件功能(我正在交换处理程序和中间件,他们有相同的函数签名 - 也许 handler 更适合向调用next()
的人发送响应和中间件的函数。但是如果没有应用这个中间件的背景,很难说。
请参阅Writing Middleware以及Express提供的其他指南。
PS。您不需要在中间件中return next()
。只需next()
。