98

我在 node.js 中使用 Express 框架和一些中间件功能:

var app = express.createServer(options);
app.use(User.checkUser);

我可以使用.use带有附加参数的函数来仅在特定路径上使用此中间件:

app.use('/userdata', User.checkUser);

是否可以使用路径变量,以便将中间件用于除特定路径(即根路径)之外的所有路径?

我正在考虑这样的事情:

app.use('!/', User.checkUser);

User.checkUser除了根路径外,总是调用so 。

4

7 回答 7

162

我会将 checkUser 中间件添加到我的所有路径中,除了主页。

app.get('/', routes.index);
app.get('/account', checkUser, routes.account);

或者

app.all('*', checkUser);
    
function checkUser(req, res, next) {
  if ( req.path == '/') return next();

  //authenticate user
  next();
}

您可以扩展它以在非身份验证路径数组中搜索 req.path:

function checkUser(req, res, next) {
  const nonSecurePaths = ['/', '/about', '/contact'];
  if (nonSecurePaths.includes(req.path)) return next();

  //authenticate user
  next();
}
于 2012-10-16T23:01:49.483 回答
14

与其直接注册User.checkUser为中间件,不如注册一个新的辅助函数,例如checkUserFilter,它会在每个 URL 上调用,但仅在给定的 URL 上将执行传递给 userFiled。例子:

var checkUserFilter = function(req, res, next) {
    if(req._parsedUrl.pathname === '/') {
        next();
    } else {
        User.checkUser(req, res, next);
    }
}

app.use(checkUserFilter);

理论上,您可以提供 regexp 路径到app.use. 例如:

app.use(/^\/.+$/, checkUser);

在 express 3.0.0rc5 上尝试过,但它不起作用。

也许我们可以开一张新票并建议将其作为一项功能?

于 2012-10-16T19:13:16.260 回答
14

您也可以在每条路由上设置中间件。

// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })

// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
  if (!req.body) return res.sendStatus(400)
  res.send('welcome, ' + req.body.username)
})
于 2016-11-22T14:43:34.343 回答
5

采用

app.use(/^(\/.+|(?!\/).*)$/, function(req, resp, next){...

这会传递除 / 之外的任何 url。除非,它对我有用。

一般来说

/^(\/path.+|(?!\/path).*)$/

(请参阅如何在正则表达式中否定特定单词?

希望这可以帮助

于 2015-09-22T13:28:53.997 回答
3

使用这个名为express-unless 的库

要求对每个请求进行身份验证,除非路径是 index.html。

app.use(requiresAuth.unless({
  path: [
    '/index.html',
    { url: '/', methods: ['GET', 'PUT']  }
  ]
}))

路径可以是字符串、正则表达式或任何这些的数组。它也可以是一个对象数组,它是 URL 和方法键对。如果请求路径或路径与方法匹配,则中间件不会运行。

这个库肯定会帮助你。

于 2019-02-20T08:58:42.377 回答
2

解决方案是使用设置api和中间件的顺序。在你的情况下,它必须是这样的。

 var app = express.createServer(options);
    
    // put every api that you want to not use checkUser here and before setting User.checkUser
    app.use("/", (req, res) => res.send("checkUser middleware is not called"));
    
    
    app.use(User.checkUser);
    
    // put every api that you want use checkUser
    app.use("/userdata", User.checkUser, (req, res) =>
      res.send("checkUser called!")
    );

这是一个完整的例子。

const express = require("express");
const app = express();
const port = 3002;

app.get("/", (req, res) => res.send("hi"));

app.use((req, res, next) => {
  console.log("check user");
  next();
});

app.get("/checkedAPI", (req, res) => res.send("checkUser called"));

app.listen(port, () => {
  console.log(`Server started at port ${port}`);
});
于 2021-06-08T11:34:04.683 回答
0

@chovy 的解决方案是最好的。

另一种解决方案是:

我面临着类似的问题。所以我所做的就是将“路​​由”文件中的函数拆分成不同的文件,分别导出。同样,我将它们分别导入到“服务器”文件中,并为各自的路由调用中间件。但我不会大规模推荐这个,我有一个不到 10 条路线的小项目,所以我不介意这样做。对于缩放,我会选择 chovy 的方法。

于 2020-12-12T08:47:56.030 回答