从快速中间件中排除路由

kre*_*eek 22 javascript middleware node.js coffeescript express

我有一个节点应用程序像其他微服务前面的防火墙/调度程序一样坐着,它使用如下的中间件链:

...
app.use app_lookup
app.use timestamp_validator
app.use request_body
app.use checksum_validator
app.use rateLimiter
app.use whitelist
app.use proxy
...
Run Code Online (Sandbox Code Playgroud)

但是对于特定的GET路由,我想跳过除rateLimiter和proxy之外的所有路由.他们是否可以使用Rails before_filter设置过滤器:除了/:仅?

luk*_*zer 63

即使在expressjs中没有内置中间件过滤系统,您也可以通过至少两种方式实现这一点.

第一种方法是将要跳过的所有中间件安装到正则表达式路径而不是包含否定查找:

// Skip all middleware except rateLimiter and proxy when route is /example_route
app.use(/\/((?!example_route).)*/, app_lookup);
app.use(/\/((?!example_route).)*/, timestamp_validator);
app.use(/\/((?!example_route).)*/, request_body);
app.use(/\/((?!example_route).)*/, checksum_validator);
app.use(rateLimiter);
app.use(/\/((?!example_route).)*/, whitelist);
app.use(proxy);
Run Code Online (Sandbox Code Playgroud)

第二种方法,可能更具可读性和更清晰,是用一个小帮助函数包装你的中间件:

var unless = function(path, middleware) {
    return function(req, res, next) {
        if (path === req.path) {
            return next();
        } else {
            return middleware(req, res, next);
        }
    };
};

app.use(unless('/example_route', app_lookup));
app.use(unless('/example_route', timestamp_validator));
app.use(unless('/example_route', request_body));
app.use(unless('/example_route', checksum_validator));
app.use(rateLimiter);
app.use(unless('/example_route', whitelist));
app.use(proxy);
Run Code Online (Sandbox Code Playgroud)

如果您需要比简单更强大的路由匹配path === req.path,则可以使用Express内部使用的path-to-regexp模块.

  • 我知道这很旧,但我想知道为什么有人指出正则表达式已损坏。当路由为 `/example_route` 时,您的正则表达式仍然匹配 `/`,因此不会跳过路由。@guillaume 在下面给出了正确的几个答案:`/^\/(?!path1|pathn).*$/` (2认同)

kj0*_*007 13

您还可以通过在req.originalUrl上添加条件来跳过这样的路由:

app.use(function (req, res, next) {

    if (req.originalUrl === '/api/login') {
    return next();
    } else {
         //DO SOMETHING
    }
Run Code Online (Sandbox Code Playgroud)


小智 9

基于@lukaszfiszer的答案,因为我想排除多个路线。您可以在此处添加任意数量的内容。

var unless = function(middleware, ...paths) {
  return function(req, res, next) {
    const pathCheck = paths.some(path => path === req.path);
    pathCheck ? next() : middleware(req, res, next);
  };
};

app.use(unless(redirectPage, "/user/login", "/user/register"));
Run Code Online (Sandbox Code Playgroud)

无法添加为评论,对不起。

  • 只是将其全部转换为 ES6 和一行: `const except = (middleware, ...paths) => (req, res, next) => paths.some(path => path === req.path )?next() : 中间件(req, res, next);` (4认同)