【问题标题】:Express 4 middleware when route is not found (finalhandler not called): how to check for it?找不到路由时的Express 4中间件(未调用finalhandler):如何检查它?
【发布时间】:2016-07-31 06:18:01
【问题描述】:

我设置了以下 Express 4 中间件堆栈:

const app = express();
const router = express.Router();
router.get('/test', testResponse);
app.use(checkAccessToken);
app.use(router);
app.use(sendResponse);
//Error Handling
app.use(function(err,req,res,next) {
  // ... Do something here
});

function sendResponse(req, res) {
  res.json({
    data: res.locals.data,
    meta: res.locals.meta
  });
}

如果我使用不存在的路由(如 GET /something)调用服务器,则在调用路由器处理程序之后调用函数 sendResponse 并且调用者得到标准响应而不是通常的消息“Cannot GET /something” ,来自 finalhandler 模块。
我认为应该调用错误处理程序,但事实并非如此。
如果找不到路由,是否有办法强制路由器发出错误,或者如果路由未匹配,则检查标准响应处理程序?
我知道我可以在 res.locals 中为任何匹配的路由添加一个值,并在标准响应处理程序中检查它,但我想使用“正确”的方式来做,而不是使用解决方法.

【问题讨论】:

  • app.use(sendResponse);改成app.use(function(req, res, next) { next(new Error(404)); });能解决你的问题吗? .
  • 完全没有,因为在这种情况下,即使找到路由也会引发错误 404
  • 你是在router函数中调用next()来调用sendResponse吧?
  • router 函数是标准的 express 路由器,所以是的,显然有一个 next() 调用,实际上它总是调用我的 sendResponse(现在上面添加的代码)

标签: node.js express middleware


【解决方案1】:

您可以查看req.route

var express = require('express');
var app = express();
app.use(require('body-parser').urlencoded({extended: false}));

const router = express.Router();

router.use(function(req, res, next) {
    app.locals.test = 0;  
    next();
});

router.get('/', function(req, res, next) {
    app.locals.test = 10;  
    next();
});

router.get('/about', function(req, res, next) {
    app.locals.test = 20;  
    next();
});

router.use(function(req, res, next) {
    if (!req.route)
        return next (new Error('404'));  
    next();
});

router.use(function(err, req, res, next){
    res.send(err.message);
})

router.use(function(req, res){
    res.send(app.locals.test + '');
});

app.use(router);

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

【讨论】:

  • 是的!检查 req.route 是我想要的,谢谢
【解决方案2】:

我使用以下逻辑:

...

app.use(require('./routes/eInvoice'))
app.use(require('./routes/oauth2/client'))

// Status 404 (Error) middleware
app.use('*', function(req,res){
    res.status(404)
    if(req.headers.accept.indexOf('html'))
        res.render('404', { url: req.protocol + '://' + req.get('host') + req.originalUrl })
    else
        res.send("URL cannot found")
})

// Error handling
app.use(require("./middlewares/errorHandler"))

app.listen(config.operating.port, function() {
    console.log('Operating Server is listening HTTP port ' + config.operating.port)
})

希望这会有所帮助..

【讨论】:

  • 我认为您正在发送路由文件中的响应,而我正在使用最后一个中间件函数发送响应。在您的情况下,您甚至不需要添加“*”路线,因为 express 已经通过 finalhandler 模块很好地处理了这种情况。
  • 是的,你是对的。我可以删除“*”部分。大约两年前我写了这段代码:)
【解决方案3】:

错误处理程序是为了防止出现未捕获的错误。没有匹配的路线不是错误。 我假设您的路由器调用的中间件不会将响应返回给客户端,因此您需要 sendResponse 中间件。 您可以更改它并将响应返回给路由器中间件中的客户端,并且在路由器使用返回未找到路由错误的中间件之后。如果你得到了这个中间件,这意味着没有匹配到路由。

【讨论】:

  • 没错,但实际上我有一百多个路由,我不想在所有路由中都对 sendResponse 进行相同的调用。只有一个 sendResponse(从 res.locals.data 中获取数据)作为中间件,看起来非常简洁。
猜你喜欢
  • 1970-01-01
  • 2014-08-07
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2014-06-25
  • 1970-01-01
相关资源
最近更新 更多