Expressjs - 所有路由都是 404

Posted

技术标签:

【中文标题】Expressjs - 所有路由都是 404【英文标题】:Expressjs - All Routes Are 404 【发布时间】:2013-08-26 17:27:02 【问题描述】:

在 My Express App 中,由于某种原因,所有路线都返回 404。

服务器.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'
  )

函数.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")
    )

输出是:

8 月 23 日 08:21:16 - [nodemon] 开始 node server.js HIH SR ER Express 应用程序在端口 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:pass@mymongoserver.com: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;
  )

配置/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");

有谁知道为什么所有路线都返回 404(所有路线都是 404,我只是没有日志)。

如果您需要更多代码,请告诉我。

【问题讨论】:

【参考方案1】:

如果请求到达中间件链的末尾而没有任何响应,则表示 404。所以一个常见的原因是缺少app.use(app.router)

在您的情况下,passport.deserializeUser(id, fn)passport.session() 内引发错误。 Express 将请求直接传递给您的自定义错误处理程序,绕过app.router。由于错误不是“未找到”,因此它呈现404

如果User.findOne(... 找不到用户,我可能只会返回null 的用户。您需要确保向已登录和未登录用户显示的任何模板都能处理这两种情况。

我也经常使用这个,它可能会派上用场:

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');
);

编辑:将故障排除留给后代......

如果app.use(app.router) 已经存在于您的./config/express 中,请检查之前的中间件。您可以在您的 routes.js 顶部设置一个包罗万象的路由,以确保任何命中路由器的东西都会发送 200:app.all('*', function(req,res) res.send(200, req.originalUrl) );

最后,确认require('function') 正在正确加载。我总是使用require('./function.js')

你可以注释掉你的app.use(passport...中间件函数来测试是否有问题。

如果这些都没有帮助,请发布您的 config/* javascript 文件。

【讨论】:

抱歉,这不起作用,但很好的解决方案。我在 config/* 中发布了代码。 我的下一步是定义一个自定义中间件函数,例如 var testResponse = function(req,res) res.send(200, req.originalUrl) ;,然后将 app.use(testResponse) 放在中间件链的顶部。继续沿链向下移动,直到响应 404 来识别问题中间件 哦,我刚刚注意到至少 / 没有发送响应,这将使其变为 404。routes.getroutes.sub 似乎发送响应。 看起来任何无法匹配路由的请求都应该传递给您的自定义错误处理程序。当您访问页面时,该页面是否按预期呈现您的 404500 模板?还是只发送 404 代码? 非常感谢!我遇到了同样的问题。在您的解释之后,我发现并解决了 deserializUser 中的问题

以上是关于Expressjs - 所有路由都是 404的主要内容,如果未能解决你的问题,请参考以下文章

如何将 404 错误重定向到 ExpressJS 中的页面?

ExpressJS 更改路由而不刷新

使用expressjs路由的firebase函数获取未定义的参数

expressjs文件下载内存泄漏

laravel配置路由除了 / 都是404解决办法

Laravel 除了 '/' 之外的所有路由都返回 404