为什么nodejs甚至在处理了路由请求后才返回404?

时间:2018-04-28 22:17:22

标签: node.js express

我正在使用jwtwebtokenexpressmongonodejsbcrypt作为我的后端API。我注意到我对localhost:3000/account/update路径的路由器正在执行但是在成功操作后它返回404。 Db连接很好。但邮递员的localhost:3000/account/update路线获得404为什么?

server.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const dbUtils = require('./services/dbconnect');
module.exports = app;

// get an instance of the router for account api routes.
const accountRoutes = require('./services/account');
const registerRoutes = require('./services/register');
const authenticateRoutes = require('./services/authentication');

// used to create, sign, and verify tokens
const jwt = require('jsonwebtoken');

// Secret key to generate new tockens.
app.set('superSecret', "11111"); // secret variable
// parse application/json
app.use(bodyParser.json())

app.use('/account', accountRoutes);
app.use('/authenticate', authenticateRoutes);
app.use('/register', registerRoutes);
app.get('/', (req, res) => res.send('Hello World!'));

dbUtils.connectToServer(() =>{

    app.listen(3000, () => console.log('Server listening on port 3000!'));
});

每个-request.js

const jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
const app = require('./../server');
function verifyLoginTokenForEachRequest(req, res, next) {
    // check header parameters for token
  const token = req.headers['x-access-token'];
  try {
    if (token) {
      // verifies secret and checks exp
      jwt.verify(token, app.get('superSecret'), (err, decoded) => {   
        console.log(decoded);

        if (err) {
          throw err || new Error('not authorized')
        } else {
          // if everything is good, save to request for use in other routes
          req.decoded = decoded;
          console.log("[authorized] user logged in")
          next();
        }
      });
    } else {
      // if there is no token, return an error
      return res.status(403).send({msg: "not authorized"});
    }
  } catch(e) {
    console.log("[unauthorized]", e);     
    return res.status(401).json({ msg: 'Failed to authenticate token.' });    
  } finally{
    next();
  }
}

module.exports={verifyLoginTokenForEachRequest};

account.js

const express = require('express')
const router = express.Router();
const verifyLoginTokenForEachRequest = require('./each-request').verifyLoginTokenForEachRequest;
const dbUtils = require('./dbconnect');

router.use(verifyLoginTokenForEachRequest);

router.post('/update', (req, res) => {
    const body = req.body;
    const db = dbUtils.getDb();
    console.log(body);
    try {
        db.collection('users')
        .updateOne({emailid: body.emailid},{$set:{firstName: body.firstName, lastName: body.lastName, lastModified: body.lastModified}},function(err, doc){
            if(err || !doc) {
                console.log(err);
                throw err || new Error('Failed to update')
            }  else {
                console.log("[success] update success");
                console.log(doc)
                res.status(200).send();
            }
        });
    } catch(e) {
        console.error("[error] failed to update");            
        res.status(500).send({msg: 'failed to update'});
    }
});

module.exports = router;

1 个答案:

答案 0 :(得分:2)

我在这里看到了很多问题。我不确定哪些确切地做了或者没有完全按照你的要求加起来,但你需要先清理这些问题,然后看看还有什么问题(如果有的话)。

  1. 您的verifyLoginTokenForEachRequest()功能始终在呼叫next(),即使已经发送了401或403响应。如果您发送回复,请不要致电next()next()告诉Express继续前往下一条路线。一旦您发送了回复,您就完成了。停止进一步路由。请勿拨打next()

  2. verifyLoginTokenForEachRequest()中,您试图通过在异步回调中执行throw xxx来创建错误条件,然后期望在更高级别捕获它。那样不行。异常只会回到jwt.verify()的内容中,并且不会进入异常处理程序。异步异常(除非它们是promise .then()处理程序的一部分)将无处可去。你不能在更高的层次上抛出它们。你必须在它们发生的地方处理它们。在这种情况下,您应该直接发送错误响应。

  3. verifyLoginTokenForEachRequest()中,当您很可能已经发送了回复时,您在finally子句中调用了next()。只有在您希望路由继续到其他路由处理程序并且尚未发送响应时才调用next()

  4. router.post('/update', ...)中,您再次在异步回调中抛出异常,异常处理程序不会捕获该异常回调。不能这样做。在那里发送错误响应或使用promises,这样您就可以更容易地将错误传播到更高级别。

  5. 这是verifyLoginTokenForEachRequest()的固定版本:

    const jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
    const app = require('./../server');
    
    function verifyLoginTokenForEachRequest(req, res, next) {
        // check header parameters for token
        const token = req.headers['x-access-token'];
        if (token) {
            // verifies secret and checks exp
            jwt.verify(token, app.get('superSecret'), (err, decoded) => {
                console.log(decoded);
    
                if (err) {
                    console.log("[verifyLoginTokenForEachRequest]", err);
                    return res.status(401).json({msg: 'Failed to authenticate token.'});
                } else {
                    // if everything is good, save to request for use in other routes
                    req.decoded = decoded;
                    console.log("[authorized] user logged in")
                    next();
                }
            });
        } else {
            // if there is no token, return an error
            return res.status(403).send({msg: "not authorized"});
        }
    }
    
    module.exports = {
        verifyLoginTokenForEachRequest
    };
    

    这是account.js的固定版本:

    const express = require('express')
    const router = express.Router();
    const verifyLoginTokenForEachRequest = require('./each-request').verifyLoginTokenForEachRequest;
    const dbUtils = require('./dbconnect');
    
    router.use(verifyLoginTokenForEachRequest);
    
    router.post('/update', (req, res) => {
        const body = req.body;
        const db = dbUtils.getDb();
        console.log(body);
        db.collection('users')
          .updateOne({emailid: body.emailid},{$set:{firstName: body.firstName, lastName: body.lastName, lastModified: body.lastModified}},function(err, doc){
            if(err || !doc) {
                console.error("[error] failed to update", err);            
                res.status(500).send({msg: 'failed to update'});
            }  else {
                console.log("[success] update success");
                console.log(doc);
                res.end();
            }
        });
    });
    
    module.exports = router;