简体   繁体   English

从 express 中间件中排除路由

[英]Exclude route from express middleware

I have a node app sitting like a firewall/dispatcher in front of other micro services and it uses a middleware chain like below:我有一个节点应用程序,就像其他微服务前面的防火墙/调度程序一样,它使用如下中间件链:

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

However for a particular GET route I want to skip all of them except rateLimiter and proxy.但是,对于特定的 GET 路由,我想跳过除 rateLimiter 和代理之外的所有路由。 Is their a way to set a filter like a Rails before_filter using :except/:only?他们是否可以使用 :except/:only 设置像 Rails before_filter 这样的过滤器?

Even though there is no build-in middleware filter system in expressjs, you can achieve this in at least two ways.尽管 expressjs 中没有内置的中间件过滤系统,但您至少可以通过两种方式实现这一点。

First method is to mount all middlewares that you want to skip to a regular expression path than includes a negative lookup:第一种方法是将所有要跳过的中间件挂载到正则表达式路径,而不是包含否定查找:

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

Second method, probably more readable and cleaner one, is to wrap your middleware with a small helper function:第二种方法,可能更易读和更清晰,是用一个小的辅助函数包装你的中间件:

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

If you need more powerfull route matching than simple path === req.path you can use path-to-regexp module that is used internally by Express.如果您需要比简单path === req.path更强大的路由匹配path === req.path您可以使用 Express 内部使用的path-to-regexp 模块

UPDATE :- In express 4.17 req.path returns only '/', so use req.baseUrl :更新:- 在express 4.17 req.path只返回“/”,所以使用req.baseUrl

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

Built upon the answer from @lukaszfiszer as I wanted more than one route excluded.建立在@lukaszfiszer 的回答之上,因为我希望排除不止一条路线。 You can add as many as you want here.您可以在此处添加任意数量。

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

Can't add as comment sorry.无法添加为评论抱歉。

You can also skip route like this by putting a condition on req.originalUrl:您还可以通过在 req.originalUrl 上设置条件来跳过这样的路由:

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

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

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

You can define some routes like below.您可以定义一些路由,如下所示。

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

    //A personal middleware
    //code

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

There's a lot of good answers here.这里有很多很好的答案。 I needed a slightly different answer though.不过,我需要一个稍微不同的答案。

I wanted to be able to exclude middleware from all HTTP PUT requests.我希望能够从所有 HTTP PUT 请求中排除中间件。 So I created a more general version of the unless function that allows a predicate to be passed in:所以我创建了一个更通用的unless函数版本,它允许传入一个谓词:

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

Example usage:用法示例:

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

Here's an example of using path-to-regexp as @lukaszfiszer's answer suggests:这是一个使用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;

The way I achieved this is by setting up a middleware for a specific path like so我实现这一点的方法是为特定路径设置中间件,如下所示

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

and then setting up my routes like so然后像这样设置我的路线

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

For the other special route that doesn't need all the middleware, we setup another route like so对于不需要所有中间件的其他特殊路由,我们设置另一条路由,如下所示

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

and then setting up the corresponding route like so然后像这样设置相应的路线

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

The Express documentation for this is available here Express 文档可在此处获得

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM