为什么我的中间件执行两次?

我在express.js / node.js中编写了一个中间件,用于检查会话,以及是否find用户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,显示用户的菜单。

我正在加载一个testing页面,我没有使用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); 

中间件运行两次的原因是它正在为初始请求运行一次,为404(不存在的静态脚本)运行一次。

如果express.static可以find一个文件,它会发送响应给相应的文件,如果找不到正确的文件(就像你的情况一样),它会调用next()来尝试将请求匹配到其他路由,运行下面定义的任何其他中间件express.static

换句话说,如果express.static确实find要提交的文件,那么它下面的中间件将不会运行。 在你的情况下,中间件运行一次实际的请求,一旦试图find文件或正确的路线作为回应。

这可以通过logging正常静态文件的req.path和不存在的文件来观察:

app.js –

 app.use(express.static(path.join(__dirname, 'public'))); app.use(function(req, res, next){ console.log('Requested path: %s', req.path); next(); }) 

layout.hbs(呈现'/') –

 <!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> 

我们将看到中间件只会logging初始请求和404的请求path,而不是静态文件。 例如:

 Requested path: / Requested path: /stylesheets/foo.css 

希望这可以帮助。

你在哪里申请这个中间件?

例如,如果你有

 app.use(handler) 

其中handler的formsfunction (req, res, next) ,它将应用于每个请求(使用任何HTTP动词)。 或者,

 app.get('/some/route', handler) 

handler将适用于/some/route (eg /some/route/any/deepness )之下的/some/route/any/deepness

所以我的猜测是,你正在使用中间件function (我正在交换处理程序中间件 ,它们具有相同的函数签名 – 也许处理程序更适合于向那些调用next()人发送响应和中间件的函数)。 但是如果没有这个中间件如何应用的背景很难说。

请参阅编写中间件和Express提供的其他指南。

PS。 你不需要在中间件中return next() 。 就next()