skip to Main Content

So this project was working fine before today, but after a bit of a nooby mistake with git I broke my project, and was unable to recover the commit. After spending some time getting everything fixed, my routes are now broken. My issue is that when calling my API routes now the server hangs for exactly 1 minute, then times out and logs a 404 on the server.

To give some background I’m using this boilerplate. In my debugging process I basically put console.logs everywhere I possibly could, and it looks like all my initialization middleware for express and passport are working fine, and my code is getting to where the routes are defined with no errors.

Middleware with app.use works and all checks out when a request is made, and all console.logs I’ve put there show fine. The console.logs only stop appearing in the final route definition like in this example:

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

My actual routes do have a res.send(), this is just an example to show you. All the console.logs I put in the middleware before this route show when the request is made, so it is hanging somewhere in app here.

It’s a rather large project, so if you want specific code examples just ask and I’ll post it. But I was able to recover all the important files that I had saved somewhere else and I’m pretty sure all my code is back to how it was before now.

edit:

Here is my file with express middleware definitions:
config/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' })
    });

  })
}

I also have another file with passport route definitions if you’d like to see that too, but all that is tested and works okay too.

edit 2:

This is my entry point file:
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;

edit 3:

Here are my route definitions:
config/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' });
            }
        });
    }
}

2

Answers


  1. If app.use works, my guess would be your protocol, is the app.get correct? You issue is otherwise located somewhere else in your code base as your sample runs fine as a single route express app.

    Login or Signup to reply.
  2. It sounds like one of three things:

    1. Somewhere in your middleware chain, you are not calling next() to allow it to advance to the next level of handlers and thus the request just eventually times out waiting for that middleware to finish (this seems to match the symptoms you describe).

    2. Somehow, your app.get() doesn’t actually match the route you expect it to or is not specified correctly.

    3. You’re using a router, but have not configured it correctly.

    But, because you don’t get an immediate 404, but rather it times out, it is probably option #1 above.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search