Ari Porad
Ari Porad

Reputation: 2922

Expressjs - All Routes Are 404

In My Express App, for some reason, all of the routes are returning 404.

Server.js

/**
 * Module dependencies
 */

var express = require('express')
var passport = require('passport')
var env = process.env.NODE_ENV || 'development'
var config = require('./config/config')[env]
var mongoose = require('mongoose')
var fs = require('fs')

require('./helpers')
require('express-namespace')

mongoose.connect(config.db)

// Bootstrap models
fs.readdirSync(__dirname + '/app/models').forEach(function (file) {
  if (~file.indexOf('.js')) require(__dirname + '/app/models/' + file)
})

// Bootstrap passport config
require('./config/passport')(passport, config)

var app = express()

// Bootstrap application settings
require('./config/express')(app, config, passport)

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

// Start the app by listening on <port>
var port = config.port || process.env.PORT || 3000
app.listen(port)
console.log('Express app started on port '+port)

// Expose app
module.exports = app

Routes.js

/**
 * Module dependencies.
 */

var mongoose = require('mongoose')
var passportOptions = {
  failureFlash: 'Invalid email or password.',
  failureRedirect: '/login'
}

// controllers
var home = require('home')
var functions = require('function')

/**
 * Expose
 */

module.exports = function (app, passport) {

  console.log("SR");
  app.get('/', function(req,res){
    console.log("//////");
  })
  app.get('/functions/get',functions.get)
  app.post('/functions/submit',functions.sub)
  app.get('/login',passport.authenticate('google',{
    "scope":"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
    "hd":"kinokiapp.com"
  }))
  app.get('/google/callback',passport.authenticate('google', { failureRedirect:"/" }),function(req,res){
    res.end("auth")
  })

console.log("ER");
}

Home.js

/*!
 * Module dependencies.
 */

console.log("HIH");

exports.index = function (req, res) {
  res.render('home', {
    title: 'Node Express Mongoose Boilerplate'
  })
}

function.js

var mongoose = require('mongoose')

var KIFunction = mongoose.model("KIFunction")

exports.get = function(req, res) {
    res.type('text/kinoki-function')
    res.status(200);
    var exclude
    try {
        exclude = JSON.parse(req.query.n)
    } catch (e) {
        exclude = []
    }
    for (var i = 0; i < exclude.length; i++) {
        if (typeof exclude[i] != 'string') {
            continue;
        }
        exclude[i] = mongoose.Types.ObjectId(exclude[i])
    }
    KIFunction.random({
        "_id":{
            "$nin":exclude
        },
        approved1:true,
        approved2:true,
    }).limit(10).exec(function(err,functions){
        if (err || functions.length == 0) {return res.end("false")}
        var out = ''
        functions.forEach(function(f){
            out += "{0}#{1}#{2}#{3}|".format(f.steps, f.string, f.difficulty, f._id)
        })

        res.end(out.substring(0, out.length - 1),"utf8")
    })
}


exports.sub = function(req,res){
    var fstr = req.body.str
    if (!(req.body.hasOwnProperty("str")) || !(fstr.match(KIFunction.functionRegex()))) {
        res.status(400)
        res.end("false")
        return
    }

    new KIFunction({
        string:fstr
    }).save(function(err){
        if(err) {
            res.status(200)
            return res.end("false")
        }
        res.status(200)
        res.end("true")
    })
}

the output is:

23 Aug 08:21:16 - [nodemon] starting node server.js HIH SR ER Express app started on port 3000 GET / 404 571ms - 863b

config/config.js

/*!
 * Module dependencies.
 */

var path = require('path')
var rootPath = path.resolve(__dirname + '../..')

/**
 * Expose config
 */

module.exports = {
  development: {
    root: rootPath,
    db: 'mongodb://localhost/kinoki_dev',
    rootURL:"http://localhost/",
    logger: 'dev'
  },
  test: {
    root: rootPath,
    db: 'mongodb://localhost/kinoki_test',
    rootURL:"http://localhost/",
    port: 9273,
    logger: false
  },
  ci: {
    root: rootPath,
    db: ("mongodb://" + process.env.WERCKER_MONGODB_HOST + ":" + process.env.WERCKER_MONGODB_PORT + "/kinoki_ci"),
    port: 2547,
    rootURL:"http://localhost/",
    logger: false
  },
  production: {
    root: rootPath,
    dbpass:"xyz",
    db: 'mongodb://user:[email protected]:39768/kinoki',
    rootURL:"http://kinokiapp.com/",
    logger: 'dev'
  }
}

config/express.js

/*!
 * Module dependencies.
 */

var express = require('express')
var mongoStore = require('connect-mongo')(express)
var helpers = require('view-helpers')
var pkg = require('../package')
var flash = require('connect-flash')
var env = process.env.NODE_ENV || 'development'
var config = require("./config")[env]

/*!
 * Expose
 */

module.exports = function (app, config, passport) {
  // Add basic auth for staging
  if (env === 'staging') {
    app.use(express.basicAuth(function(user, pass){
      return 'username' == user & 'password' == pass
    }))

    app.use(function (req, res, next) {
      if (req.remoteUser && req.user && !req.user._id) {
        delete req.user
      }
      next()
    })
  }

  app.set('showStackError', true)

  // use express favicon
  app.use(express.favicon(config.root + '/public/favicon.ico'))

  app.use(express.static(config.root + '/public'))
  if(config.logger){
    app.use(express.logger(config.logger))
  }

  // views config
  app.set('views', config.root + '/app/views')
  app.set('view engine', 'jade')

  app.configure(function () {
    // bodyParser should be above methodOverride
    app.use(express.bodyParser())
    app.use(express.methodOverride())

    // cookieParser should be above session
    app.use(express.cookieParser())
    app.use(express.session({
      secret: pkg.name,
      store: new mongoStore({
        url: config.db,
        collection : 'sessions'
      })
    }))

    // Passport session
    app.use(passport.initialize())
    app.use(passport.session())

    // Flash messages
    app.use(flash())

    // expose pkg and node env to views
    app.locals({
      pkg:pkg,
      env:env
    })

    // View helpers
    app.use(helpers(pkg.name))

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

    // custom error handler
    app.use(function (err, req, res, next) {
      if (err.message
        && (~err.message.indexOf('not found')
        || (~err.message.indexOf('Cast to ObjectId failed')))) {
        return next()
      }

      console.error(err.stack)
      res.status(500).render('500')
    })

    app.use(function (req, res, next) {
      res.status(404).render('404', { url: req.originalUrl })
    })
  })

  // development specific stuff
  app.configure('development', function () {
    app.locals.pretty = true;
  })

  // staging specific stuff
  app.configure('staging', function () {
    app.locals.pretty = true;
  })
}

config/passport.js

/*!
 * Module dependencies.
 */

var mongoose = require('mongoose')
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy
var User = mongoose.model('User')
var config = require('./config')[process.env.NODE_ENV]

/**
 * Expose
 */

module.exports = function(passport, config) {
  // serialize sessions
  passport.serializeUser(function(user, done) {
    done(null, user.id)
  })

  passport.deserializeUser(function(id, done) {
    User.findOne({
      _id: id
    }, function(err, user) {
      done(err, user)
    })
  })

  passport.use(new GoogleStrategy({
    clientID: process.env.GOOGLE_ID,
    clientSecret: process.env.GOOGLE_SECRET,
    callbackURL: config.rootURL + 'google/callback'
  },
  function(accessToken, refreshToken, profile, done) {
    User.findOne({
        id: profile.id
      }, function(err, user) {
        if (err) {
          return done(err)
        }
        if (!user) {
          user = new User({
            id: profile.id,
            profile: profile,
            accessToken:accessToken,
            refreshToken:refreshToken
          })
          user.save(function(err) {
            if (err) {
              return done(err)
            }
            done(null, user)
          })
        } else {
          done(null,user)
        }       
      })
  }
))

  passport.reqAuth = function(req,res,next){
    if(req.isAuthenticated())
      return next()
    else
      res.redirect('/login')
  }
}

config/routes.js

/**
 * Module dependencies.
 */

var mongoose = require('mongoose')
var passportOptions = {
  failureFlash: 'Invalid email or password.',
  failureRedirect: '/login'
}

// controllers
var home = require('home')
var functions = require('function')

/**
 * Expose
 */

module.exports = function (app, passport) {

  console.log("SR");
  app.get('/', function(req,res){
    console.log("//////");
  })
  app.get('/functions/get',functions.get)
  app.post('/functions/submit',functions.sub)
  // app.get('/login',passport.authenticate('google',{
  //    "scope":"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
  //    "hd":"kinokiapp.com"
  // }))
  // app.get('/google/callback',passport.authenticate('google', { failureRedirect:"/" }),function(req,res){
  //    res.end("auth")
  // })

console.log("ER");
}

Does Anyone Know why all the routes are returning 404 (all of them are 404, i just don't have the logs).

Please let me know if you need more code.

Upvotes: 3

Views: 6497

Answers (1)

Plato
Plato

Reputation: 11052

Express 404's if a request gets to the end of the middleware chain without anything sending a response. So a common reason for this is a missing app.use(app.router).

In your case passport.deserializeUser(id, fn) throws an error within passport.session(). Express passes the request directly to your custom error handler, bypassing app.router. Since the error is not 'not found' it renders 404.

I would probably just return a user of null in the event that User.findOne(... doesn't find a user. You will need to make sure any templates that are shown to both logged-in and non-logged-in users handles both cases.

Also I use this often, it might come in handy:

function restrictToLoggedIn(req, res, next){
  if(req.user && req.user !== null){ 
    return next() 
  } else {
    res.send(401, 'Must be logged in');
  };
};

app.get('/'
, restrictToLoggedIn
, function(req, res, next){
// req.user is guranteed to be populated
  res.locals.user = req.user;
  res.render('home');
});

edit: leaving troubleshooting for posterity...

If app.use(app.router) already exists in your ./config/express, check the previous middlewares. You can set a single catchall route at the top of your routes.js to make sure that anything that hits the router sends 200: app.all('*', function(req,res){ res.send(200, req.originalUrl) });

Finally, confirm that require('function') is loading properly. I always use require('./function.js').

You can comment out your app.use(passport... middleware functions to test whether that's at fault.

If none of this helps please post your config/* javascript files.

Upvotes: 9

Related Questions