Node.js 为什么nodejs即使在处理路由请求后仍返回404?

Node.js 为什么nodejs即使在处理路由请求后仍返回404?,node.js,express,Node.js,Express,我正在为我的后端API使用jwtwebtoken、express、mongo、nodejs、bcrypt。我注意到我为localhost:3000/account/updatepath配置的路由器正在执行,但成功运行后返回404。数据库连接正常。但是postman中的localhost:3000/account/update路由得到404为什么 server.js const express = require('express'); const app = express(); const b

我正在为我的后端API使用
jwtwebtoken
express
mongo
nodejs
bcrypt
。我注意到我为
localhost:3000/account/update
path配置的路由器正在执行,但成功运行后返回404。数据库连接正常。但是postman中的
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!'));
});
each-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;

我认为这里有很多问题是错误的。我不确定哪些问题确实符合或不符合您的要求,但您需要首先解决这些问题,然后看看还剩下什么问题(如果有)

  • 您的
    verifyLoginTokenForEachRequest()
    函数总是调用
    next()
    ,即使它已经发送了401或403响应。如果发送响应,不要调用
    next()
    next()
    告诉Express继续走下一条路线。一旦您发送了响应,您就完成了。停止进一步的路由。不要调用
    next()

  • verifyLoginTokenForEachRequest()
    中,您试图创建一个错误条件,方法是在异步回调中执行
    抛出xxx
    ,然后期望在更高级别捕获该错误。那是行不通的。异常将返回到
    jwt.verify()
    的内部,而不会进入异常处理程序。异步异常(除非它们是promise
    .then()
    处理程序的一部分)将不会出现。你不能在更高的水平上投球和接球。你必须在它们发生的地方处理它们。在这种情况下,您应该直接在那里发送错误响应

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

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

  • 下面是一个固定版本的
    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;
    

    我认为这里有很多问题是错误的。我不确定哪些问题确实符合或不符合您的要求,但您需要首先解决这些问题,然后看看还剩下什么问题(如果有)

  • 您的
    verifyLoginTokenForEachRequest()
    函数总是调用
    next()
    ,即使它已经发送了401或403响应。如果发送响应,不要调用
    next()
    next()
    告诉Express继续走下一条路线。一旦您发送了响应,您就完成了。停止进一步的路由。不要调用
    next()

  • verifyLoginTokenForEachRequest()
    中,您试图创建一个错误条件,方法是在异步回调中执行
    抛出xxx
    ,然后期望在更高级别捕获该错误。那是行不通的。异常将返回到
    jwt.verify()
    的内部,而不会进入异常处理程序。异步异常(除非它们是promise
    .then()
    处理程序的一部分)将不会出现。你不能在更高的水平上投球和接球。你必须在它们发生的地方处理它们。在这种情况下,您应该直接在那里发送错误响应

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

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

  • 下面是一个固定版本的
    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;