他のマイクロサービスの前にファイアウォール/ディスパッチャーのように座っているノードアプリがあり、以下のようなミドルウェアチェーンを使用しています。
...
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のようなフィルターを設定する方法はありますか?
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モジュール を使用できます。
Req.originalUrlに条件を設定して、このようなルートをスキップすることもできます。
app.use(function (req, res, next) {
if (req.originalUrl === '/api/login') {
return next();
} else {
//DO SOMETHING
}
複数のルートを除外したかったので、@ 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"));
申し訳ありませんがコメントとして追加できません。
この正規表現を使用して成功しました:/^\/(?!path1|pathn).*$/
。
以下のようないくつかのルートを定義できます。
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;