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.u
Even though there is no build-in middleware filter system in expressjs, you can achieve this in at least two ways.
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.
UPDATE :- In express 4.17
req.path
returns only '/', so use req.baseUrl
:
var unless = function(path, middleware) {
return function(req, res, next) {
if (path === req.baseUrl) {
return next();
} else {
return middleware(req, res, next);
}
};
};
Here's an example of using path-to-regexp
as @lukaszfiszer's answer suggests:
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;
Built upon the answer from @lukaszfiszer as I wanted more than one route excluded. 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 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
});
I use this regular expression with success : /^\/(?!path1|pathn).*$/
.
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