wkr-util
Version:
Utility library for wkr project.
54 lines (49 loc) • 1.88 kB
JavaScript
import {compose, split, map, trim, pick} from '@cullylarson/f'
import rateLimit from 'express-rate-limit'
import {messageObj} from '@cullylarson/validate'
import {formatIpv4, responseError} from './'
import {logLevels} from './log'
export const RateLimit = ({
tooManyErrorMessage = 'You have made too many requests to this resource. Please try again later.',
tooManyErrorKey = 'too-many-requests',
tooManyErrorStatus = 429,
rateLimitIpsWhitelistStr = null,
rateLimitIpsWhitelist = [],
logRepo = null,
...rateLimitParams
}) => {
if(rateLimitIpsWhitelistStr && (!rateLimitIpsWhitelist || !rateLimitIpsWhitelist.length)) {
rateLimitIpsWhitelist = compose(
map(trim),
split(','),
)(rateLimitIpsWhitelistStr)
}
return rateLimit({
windowMs: 5 * 60 * 1000, // 5 minutes
max: 300, // limit each IP to this many requests per windowMs
skipSuccessfulRequests: true,
skip: (req) => {
const ip = formatIpv4(req.ip)
return ip === '127.0.0.1' || rateLimitIpsWhitelist.includes(ip)
},
handler: (req, res) => {
return res.status(tooManyErrorStatus).json(responseError(messageObj(tooManyErrorKey, tooManyErrorMessage)))
},
onLimitReached: (req, res, options) => {
if(!logRepo) return
logRepo.add(
'too-many-requests',
logLevels.NOTICE,
'This IP address has made too many requests and has been rate-limited.',
{
data: {
...pick(['windowMs', 'max'], options),
...pick(['limit', 'current', 'remaining', 'resetTime'], req.rateLimit),
},
},
req,
)
},
...rateLimitParams,
})
}