web-dev-qa-db-ja.com

高速ミドルウェアからルートを除外する

他のマイクロサービスの前にファイアウォール/ディスパッチャーのように座っているノードアプリがあり、以下のようなミドルウェアチェーンを使用しています。

...
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を除くすべてをスキップします。 :except /:onlyを使用してRails before_filterのようなフィルターを設定する方法はありますか?

22
kreek

Expressjsには組み込みのミドルウェアフィルターシステムはありませんが、少なくとも2つの方法でこれを実現できます。

最初の方法は、スキップしたいすべてのミドルウェアを、ネガティブルックアップを含む正規表現パスにマウントすることです。

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

おそらくより読みやすく、よりクリーンな2番目の方法は、ミドルウェアを小さなヘルパー関数でラップすることです。

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モジュール を使用できます。

61
lukaszfiszer

Req.originalUrlに条件を設定して、このようなルートをスキップすることもできます。

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

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

複数のルートを除外したかったので、@ 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"));

申し訳ありませんがコメントとして追加できません。

7
Geelie

この正規表現を使用して成功しました:/^\/(?!path1|pathn).*$/

4
Guillaume

以下のようないくつかのルートを定義できます。

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

    //A personal middleware
    //code

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

@lukaszfiszerの答えが示唆するようにpath-to-regexpを使用する例を次に示します。

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;

0
riscarrott