从快速中间件中排除路由

时间:2014-11-25 01:30:11

标签: javascript node.js express coffeescript middleware

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

...
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
...

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

8 个答案:

答案 0 :(得分:59)

尽管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);

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

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);

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

答案 1 :(得分:12)

您也可以通过在req.originalUrl:

上添加条件来跳过这样的路线
app.use(function (req, res, next) {

    if (req.originalUrl === '/api/login') {
    return next();
    } else {
         //DO SOMETHING
    }

答案 2 :(得分:5)

基于@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"));

无法添加评论对不起。

答案 3 :(得分:4)

我成功使用这个正则表达式:/^\/(?!path1|pathn).*$/

答案 4 :(得分:1)

您可以定义一些路线,如下所示。

 app.use(/\/((?!route1|route2).)*/, (req, res, next) => {

    //A personal middleware
    //code

    next();//Will call the app.get(), app.post() or other
 });

答案 5 :(得分:1)

这里有很多好的答案。不过我需要一个略有不同的答案。

我希望能够从所有HTTP PUT请求中排除中间件。因此,我创建了unless函数的更通用版本,该函数允许传入谓词:

function unless(pred, middleware) {
    return (req, res, next) => {
        if (pred(req)) {
            next(); // Skip this middleware.
        }
        else {
            middleware(req, res, next); // Allow this middleware.
        }
    }
}

用法示例:

app.use(unless(req => req.method === "PUT", bodyParser.json()));

答案 6 :(得分:0)

下面是使用path-to-regexp作为@lukaszfiszer的答案表明的示例:

import { RequestHandler } from 'express';
import pathToRegexp from 'path-to-regexp';

const unless = (
  paths: pathToRegexp.Path,
  middleware: RequestHandler
): RequestHandler => {
  const regex = pathToRegexp(paths);
  return (req, res, next) =>
    regex.exec(req.url) ? next() : middleware(req, res, next);
};

export default unless;

答案 7 :(得分:0)

我实现此目标的方法是为这样的特定路径设置中间件

app.use("/routeNeedingAllMiddleware", middleware1);
app.use("/routeNeedingAllMiddleware", middleware2);
app.use("/routeNeedingAllMiddleware", middleware3);
app.use("/routeNeedingAllMiddleware", middleware4);

然后像这样设置我的路线

app.post("/routeNeedingAllMiddleware/route1", route1Handler);
app.post("/routeNeedingAllMiddleware/route2", route2Handler);

对于不需要所有中间件的另一条特殊路由,我们设置了另一条这样的路由

app.use("/routeNeedingSomeMiddleware", middleware2);
app.use("/routeNeedingSomeMiddleware", middleware4);

然后像这样设置相应的路线

app.post("/routeNeedingSomeMiddleware/specialRoute", specialRouteHandler);

有关此问题的Express文档可用here