【问题标题】:Route callbacks not executing but middleware is路由回调未执行但中间件是
【发布时间】:2017-02-07 14:17:04
【问题描述】:

所以这个项目在今天之前运行良好,但是在 git 出现了一个小错误之后,我破坏了我的项目,并且无法恢复提交。在花了一些时间把所有东西都修好之后,我的路线现在坏了。我的问题是,现在调用我的 API 路由时,服务器正好挂起 1 分钟,然后超时并在服务器上记录 404。

为了提供一些背景信息,我使用了this 样板。在我的调试过程中,我基本上把 console.logs 放在我可能的任何地方,看起来我所有的 express 和 passport 初始化中间件都工作正常,我的代码正在到达定义路由的地方,没有错误。

带有app.use 的中间件可以正常工作,并且在发出请求时全部检查出来,并且我放在那里的所有 console.logs 都显示正常。 console.logs 仅停止出现在最终路由定义中,如下例所示:

app.get('/route', function(req, res, next) {
    console.log('this never shows');
    next();
}, function(req, res, next) {
    console.log('this never shows');
})

我的实际路线确实有res.send(),这只是向您展示的示例。我在此路由之前放入中间件的所有console.logs都显示了何时发出请求,所以它挂在app这里的某个地方。

这是一个相当大的项目,所以如果您想要具体的代码示例,请询问,我会发布。但是我能够恢复我保存在其他地方的所有重要文件,而且我很确定我的所有代码都恢复到了以前的状态。

编辑:

这是我的包含快速中间件定义的文件: 配置/express.js

/**
 * Module dependencies.
 */

var express = require('express');
var MongoStore = require('connect-mongo')(express);
var flash = require('connect-flash');
var helpers = require('view-helpers');
var swig = require('swig');
var session = require('express-session');

module.exports = function (app, config, passport) {

  app.set('showStackError', true);
  // should be placed before express.static
  app.use(express.compress({
    filter: function (req, res) {
      return /json|text|javascript|css/.test(res.getHeader('Content-Type'));
    },
    level: 9
  }));
  app.use(express.favicon());
  app.use(express.static(config.root + '/public'));
  app.use('/uploads', express.static(config.root + '/uploads'));

  var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

    // intercept OPTIONS method
    if ('OPTIONS' == req.method) {
        res.status(204).end();
    }
    else {
        next();
    }
  };

  app.use(allowCrossDomain);

  // don't use logger for test env
  if (process.env.NODE_ENV !== 'test') {
    app.use(express.logger('dev'));
  }

  // set views path, template engine and default layout
  app.engine('html', swig.renderFile);
  app.set('view engine', 'html');
  app.set('views', config.root + '/app/views');
  app.set('view cache', process.env.NODE_ENV !== 'development');

  app.configure(function () {
    // dynamic helpers
    // app.use(function(req,res,next){
    //     req.locals.session = "eeeeeeee";
    //     next();
    // });

    // cookieParser should be above session
    app.use(express.cookieParser());

    // bodyParser should be above methodOverride
    app.use(express.bodyParser());
    app.use(express.methodOverride());

    // express/mongo session storage
    app.use(function(req, res, next) {
        if(!req.cookies['_ga']) {
            next();
        }
        else {
            session({
                secret: 'secrettexthere',
                saveUninitialized: true,
                resave: true,
                store: new MongoStore({
                    url: 'mongodb://localhost/traderdb',
                    db: 'traderdb',
                    collection: 'sessions',
                    auto_reconnect: true
                })
            })(req, res, next);
        }
    });

    // connect flash for flash messages
    app.use(flash());

    app.use(function (req, res, next) {
        res.locals.session = req.session;
        res.locals.req = req;
        next();
    });
    app.use(function(req, res, next) {
        if(!req.cookies['_ga']) {
            next();
        }
        else {
            passport.initialize()(req, res, next);
        }
    });

    //app.use(helpers('app name'));
    //
    // use passport session
    app.use(function(req, res, next) {
        if(!req.cookies['_ga']) {
            next();
        }
        else {
            passport.session()(req, res, next);
        }
    });

    // routes should be at the last
    app.use(app.router);

    // assume "not found" in the error msgs
    // is a 404. this is somewhat silly, but
    // valid, you can do whatever you like, set
    // properties, use instanceof etc.
    app.use(function(err, req, res, next) {
      // treat as 404
      if (~err.message.indexOf('not found')) return next();

      // log it
      console.error(err.stack);

      // error page
      res.status(500).render('500', { error: err.stack });
    });

    // assume 404 since no middleware responded
    app.use(function(req, res, next) {
      res.status(404).render('404', { url: req.originalUrl, error: 'Not found' })
    });

  })
}

如果您也想查看,我还有另一个包含护照路线定义的文件,但所有这些都经过测试并且工作正常。

编辑 2:

这是我的入口点文件: server.js

/**
 * Module dependencies.
 */

var express = require('express')
  , fs = require('fs')
  , passport = require('passport');

/**
 * Main application entry file.
 * Please note that the order of loading is important.
 */

// Load configurations
// if test env, load example file
var env = process.env.NODE_ENV || 'development'
  , config = require('./config/config')[env]
  , auth = require('./config/middlewares/authorization')
  , mongoose = require('mongoose');

// Bootstrap db connection
mongoose.connect(config.db);

// Bootstrap models
var models_path = __dirname + '/app/models'
fs.readdirSync(models_path).forEach(function (file) {
  require(models_path+'/'+file);
});

// bootstrap passport config
require('./config/passport')(passport, config);

var app = express();
// express settings
require('./config/express')(app, config, passport);

// Bootstrap routes
require('./config/routes')(app, passport, auth);

// Start the app by listening on <port>
var port = 3002;
app.listen(port);
console.log('Express app started on port '+port);

// expose app
exports = module.exports = app;

编辑 3:

这是我的路线定义: 配置/routes.js

var express = require('express');
var path = require('path');
var fileManager = require('express-file-manager');
var mongoose = require('mongoose');
var Session = mongoose.model('Session');

module.exports = function (app, passport, auth) {
    var users = require('../app/controllers/users');
    var coupons = require('../app/controllers/coupons');
    var magazines = require('../app/controllers/magazines');
    var zones = require('../app/controllers/zones');
    var transactions = require('../app/controllers/transactions');
    var favorites = require('../app/controllers/favorites');
    var banners = require('../app/controllers/banners');
    var reports = require('../app/controllers/reports');
    var coverContest = require('../app/controllers/coverContest');
    var contactMessage = require('../app/controllers/contactMessage');

    app.post('/api/users/login', users.login);
    app.post('/api/users/register', users.register);
    app.post('/api/users/logout', users.logout);
    app.post('/api/users/sendResetEmail', users.sendResetEmail);
    app.post('/api/users/changePassword', users.changePassword);
    app.post('/api/users/redeemCoupon', isValidAppUser(), users.redeemCoupon);
    app.get('/api/users/validate', isLoggedIn(0), function(req, res) {
        res.send(req.user);
    });

    app.post('/api/coupons', coupons.get);
    app.post('/api/coupons/import', isLoggedIn(0), coupons.import);
    app.post('/api/coupons/remove', isLoggedIn(0), coupons.remove);
    app.post('/api/coupons/upload', isLoggedIn(0), coupons.upload);

    app.post('/api/transactions', transactions.get);
    app.post('/api/allTransactions', isLoggedIn(0), transactions.getAll);

    app.post('/api/magazines', magazines.get);
    app.post('/api/magazines/import', isLoggedIn(0), magazines.import);
    app.post('/api/magazines/remove', isLoggedIn(0), magazines.remove);

    app.post('/api/banners', banners.get);
    app.post('/api/banners/import', isLoggedIn(0), banners.import);
    app.post('/api/banners/remove', isLoggedIn(0), banners.remove);

    app.post('/api/favorites', isValidAppUser(), favorites.get);
    app.post('/api/favorites/import', isValidAppUser(), favorites.import);

    app.post('/api/zones', zones.get);
    app.post('/api/zones/add', zones.add);
    app.post('/api/zones/addCoupon', zones.addCoupon);
    app.post('/api/zones/addMagazine', zones.addMagazine);

    app.post('/api/mail/ccSubmit', coverContest.ccSubmit);
    app.post('/api/mail/contactSubmit', contactMessage.contactSubmit);

    //app.get('/api/reports/siteUsers', reports.siteUsers);
    app.get('/auth/facebook', passport.authenticate('facebook', { scope: [ 'email', 'user_about_me'], failureRedirect: '/login' }), users.signin);
    app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), users.authCallback);
    app.get('/auth/github', passport.authenticate('github', { failureRedirect: '/login' }), users.signin);
    app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/login' }), users.authCallback);
    app.get('/auth/twitter', passport.authenticate('twitter', { failureRedirect: '/login' }), users.signin);
    app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/login' }), users.authCallback);
    app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
    app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/', successRedirect: '/main.html' }));
}

function isLoggedIn(secLvl) {
    return function(req, res, next) {
        if(req.isAuthenticated() && req.user.secLvl <= secLvl && req.user.google.email.includes('@bizpub36.com')) {
            return next();
        }

        res.redirect('https://accounts.google.com/logout');
    }
}

function isValidAppUser() {
    return function(req, res, next) {
        Session.findOne({ sess_id: req.body.sess_id }).exec(function(err, session) {
            if(!err && session) {
                next();
            }
            else {
                res.end({ status: 'error', message: 'invalid session' });
            }
        });
    }
}

【问题讨论】:

  • 我试试你的路线,一切都很好。在console.log('this never shows');之后添加res.json(data);res.send('something');
  • @emaniacs 这不是我的问题。如果我的 console.logs 甚至没有显示,那么它甚至不会发送响应。回调根本没有执行。我给出的代码示例只是一个示例。我的实际路线确实调用res.send()
  • 我认为,在此之前执行了另一条同名路由('/route')并完成了响应。这是我的假设。请与app._router.stackrouter.stack 联系。或者在你初始化你的应用程序之后添加那行
  • 另外一招,在process.on('exit', exitHandler)上添加handler,在exitHandler中抛出错误,可以看到详细过程。 :)
  • @emaniacs 同样,这是一个例子。我实际上没有任何名为/route 的路线。如果您阅读了我的帖子,我的代码应该是正确的,它以前可以工作。

标签: node.js express


【解决方案1】:

如果app.use 有效,我猜是你的协议,app.get 是否正确?您的问题位于代码库中的其他位置,因为您的示例作为单路由快速应用程序运行良好。

【讨论】:

  • 我只是在浏览器中访问它来测试它,所以是的,它是获取请求。我很困惑,因为在我遇到这个 git 问题之前,我的整个代码库都在工作。我已经检查了两次三次,我的所有代码看起来都和我遇到这个问题之前完全一样。
  • 如果您在代码库中注释掉除此之外的所有其他路由,它是否按预期运行?
  • 不,还是同样的问题。我很肯定我的所有路由定义都很好,因为我从旧版本的代码库中为它们获取了文件,并且它从未真正改变太多。但我仍然一遍又一遍地检查它,我确信我的路线定义正确。
  • 所以,如果你的函数没有像你换成app.use那样连续运行,我们可以计算出你所有的函数都会执行,但是一个接一个地运行就会失败。我的猜测是,您在路由器之外的某个地方出现了一个错误,没有击中控制台。基本上,您要最后运行的中间件会在出现错误或不返回的函数超时之前返回。这有意义吗?
【解决方案2】:

这听起来像是三件事之一:

  1. 在您的中间件链中的某个位置,您没有调用 next() 以允许它前进到下一级处理程序,因此请求最终会超时等待该中间件完成(这似乎与您描述的症状)。

  2. 不知何故,您的 app.get() 实际上与您期望的路线不匹配或未正确指定。

  3. 您正在使用路由器,但未正确配置。

但是,由于您没有立即收到 404,而是超时,因此可能是上面的选项 #1。

【讨论】:

  • 您的第一个选项也是我所期望的第一件事,但我已经测试了所有内容,并且我的整个中间件链完美执行,没有任何问题。我一直到我最后一个中间件定义 app.use(app.router);
  • @chrispytoes - 我从未见过app.use(app.router)。通常,它将是app.use(router),其中路由器是您创建的独立对象,然后其上的路由将是router.get()。所以,app.use(app.router) 根本不适合 app.get()。如果您需要帮助,您必须向我们展示相关的路由代码。我们在没有访问代码的情况下在黑暗中猜测。我添加了选项 3(另一个无法访问代码的猜测)。
  • app.use(app.router) 已经写在我使用的样板文件中。我已经用我的 express 中间件更新了我的帖子。
  • @chrispytoes - app.use(app.router); 看起来不对,不应该在那里。去掉它。您没有定义 app.router 并且它不是普通 Express 配置的一部分。您的实际路线应该按顺序进入该位置。说到这,您在这个序列中定义的实际路线在哪里?如果您从某个地方复制了它,那么您并没有完全了解整个方案。 app.route 不是一种正常的处理方式,除非您定义了该属性,否则它甚至不存在,并且要使其实际工作,它必须指向您定义路由的路由器。
  • @chrispytoes - 你知道那是几岁吗?那是至少 3 年前的事了,4.0 是一个相当大的变化(对于初学者来说,取消捆绑以前内置的东西)。您可能会在项目中使用的大多数现代中间件甚至可能不再使用 Express 3 进行测试。如果这是 Express 3 问题,请立即将其放在问题的开头,我将不得不选择不提供帮助。我不确定您是否能在这里找到很多人来帮助您使用 Express 3。我可能会问,您为什么使用这么旧的版本?
猜你喜欢
  • 1970-01-01
  • 2019-07-05
  • 2017-10-20
  • 2022-12-08
  • 2012-09-01
  • 1970-01-01
  • 2021-09-07
  • 2016-07-31
相关资源
最近更新 更多