It looks like your main problem is here:
}).use(rateLimiter(req))
You don't show exactly what comes before that, but if this is an app.use()
or router.use()
, then you need to fix how you pass your middleware to that to be like this:
app.use(rateLimiter)
This will pass the middleware function rateLimiter
to app.use()
so it can be called later. All middleware is called with three arguments (req, res, next)
So, you need to modify your middleware to match that.
Then, you need to use those parameters appropriately in your middleware to accomplish your goal. Here's a possible implementation that should show you how this could work.
// create middleware from your rate limiting package to later conditionally apply
const limiter = rateLimit({
windowMs: 60 * 1000,
max: config.webserver.limit,
message: {error: 'You have exceeded the requests in 1 min limit! Please try again soon.'},
headers: true,
})
const rateLimiter = (req, res, next) => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
// implement your ip address limiting here
// you should have one of three outcomes
// 1. You call next() to allow the routing to continue for this request
// 2. You call next(someError) to abort routing and fall-through to
// your Express error handler
// 3. You send a response using something like res.status(xxx).send(),
// thus ending the request
// block this request if the IP address is on the blacklist
if (blacklist.indexOf(ip) >= 0) {
res.status(403).send('You cannot use this service!');
return;
}
// if the IP address is on the whitelist, then let it go
if (whitelist.indexOf(ip) >= 0) {
// continue routing
next();
return;
}
// apply rate limiter middleware
limiter(req, res, next);
}
app.use(rateLimiter);
This creates a middleware called limiter
here and a middleware rateLimiter
. The rateLimiter
middleware will be called on every request incoming request by virtue of the app.use(rateLimiter)
. Then, inside that it will check the blacklist and the whitelist. If it's on the blacklist, it will short-circuit the request and end it with a 403. If it's on the whitelist, it will continue routing and let subsequent route handlers process it. If it's not on either list, then it will conditionally apply rate limiting to it by manually calling the rate limiting middleware and passing it the (req, res, next)
that were passed into your middleware.
Other comments on the questions you raise:
I need to apply middleware for everyone except a few IPs, but I can't get req and res outside of route, how could I apply it?
req
and res
only exist during the process of handling a given incoming request. So, once a request is over, those objects associated with that request are garbage collected and no longer available. Even if you managed to stuff them somewhere, that wouldn't do you much good because the socket associated with the res
object has finished and is likely closed and you can't continue to send more data on it anyone.
So, you don't get access to req
and res
outside of processing a route or middleware. That's where they are available and useful.
So how could I either send my IP to my middleware or check the IP in my express code and use it only if the IP is not in my whitelist file? This issue is killing me
The IP address for the incoming request is available in the req
object. Your middleware has access to that.
The usual way to do that is:
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
More discussion of that here, but from your code, it looks like you already know that.