(route, config, cloud)
| 639 | } |
| 640 | |
| 641 | export const addRateLimit = (route, config, cloud) => { |
| 642 | if (typeof config === 'string') { |
| 643 | config = Config.get(config); |
| 644 | } |
| 645 | for (const key in route) { |
| 646 | if (!RateLimitOptions[key]) { |
| 647 | throw `Invalid rate limit option "${key}"`; |
| 648 | } |
| 649 | } |
| 650 | if (!config.rateLimits) { |
| 651 | config.rateLimits = []; |
| 652 | } |
| 653 | const redisStore = { |
| 654 | connectionPromise: Promise.resolve(), |
| 655 | store: null, |
| 656 | }; |
| 657 | if (route.redisUrl) { |
| 658 | const log = config?.loggerController || defaultLogger; |
| 659 | const client = createClient({ |
| 660 | url: route.redisUrl, |
| 661 | }); |
| 662 | client.on('error', err => { log.error('Middlewares addRateLimit Redis client error', { error: err }) }); |
| 663 | client.on('connect', () => { }); |
| 664 | client.on('reconnecting', () => { }); |
| 665 | client.on('ready', () => { }); |
| 666 | redisStore.connectionPromise = async () => { |
| 667 | if (client.isOpen) { |
| 668 | return; |
| 669 | } |
| 670 | try { |
| 671 | await client.connect(); |
| 672 | } catch (e) { |
| 673 | log.error(`Could not connect to redisURL in rate limit: ${e}`); |
| 674 | } |
| 675 | }; |
| 676 | redisStore.connectionPromise(); |
| 677 | redisStore.store = new RedisStore({ |
| 678 | sendCommand: async (...args) => { |
| 679 | await redisStore.connectionPromise(); |
| 680 | return client.sendCommand(args); |
| 681 | }, |
| 682 | }); |
| 683 | } |
| 684 | config.rateLimits.push({ |
| 685 | path: pathToRegexp(route.requestPath), |
| 686 | requestCount: route.requestCount, |
| 687 | requestMethods: route.requestMethods, |
| 688 | includeMasterKey: route.includeMasterKey, |
| 689 | includeInternalRequests: route.includeInternalRequests, |
| 690 | errorResponseMessage: route.errorResponseMessage || RateLimitOptions.errorResponseMessage.default, |
| 691 | handler: rateLimit({ |
| 692 | windowMs: route.requestTimeWindow, |
| 693 | max: route.requestCount, |
| 694 | message: route.errorResponseMessage || RateLimitOptions.errorResponseMessage.default, |
| 695 | handler: (request, response, next, options) => { |
| 696 | throw { |
| 697 | code: Parse.Error.CONNECTION_FAILED, |
| 698 | message: options.message, |
no test coverage detected