moleculerjs / moleculer-web

:earth_africa: Official API Gateway service for Moleculer framework
http://moleculer.services/docs/moleculer-web.html
MIT License
292 stars 120 forks source link

Improve rate limiter #317

Closed thib3113 closed 1 year ago

thib3113 commented 1 year ago

This PR will allow to create an async rate limiter .

This allow to use an async rate limiter (for example with redis, to use a centralized store).

Also, I update some typings / exporting some more types .

Also, in the same time, I update the dev dependencies, repair a test (force LF ending, else the req.body test fail on windows) .

To test this code, I create this rateLimiter that will use my broker cacher (or memory store)

import { ServiceBroker } from 'moleculer';
import moleculer, { RateLimitSettings, RateLimitStore } from 'moleculer-web';

export abstract class RateLimiterStore implements RateLimitStore {
    private readonly keyPrefix = 'rate-limiter';
    private broker: ServiceBroker;
    private memoryStore: RateLimitStore;
    private readonly clearPeriod: number;
    private opts: RateLimitSettings;
    public resetTime: number;

    public constructor(clearPeriod: number, opts: RateLimitSettings, broker: ServiceBroker) {
        this.broker = broker;
        this.resetTime = Date.now() + clearPeriod;
        this.clearPeriod = clearPeriod;
        this.opts = opts;

        this.memoryStore = new moleculer.RateLimitStores.MemoryStore(clearPeriod, opts);
    }

    /**
     * Increment the counter by key
     */
    async inc(key: string): Promise<number> {
        this.resetTime = Date.now() + this.clearPeriod;
        if (this.broker.cacher) {
            let counter = Number(await this.broker.cacher.get(this.keyPrefix + key)) || 0;
            counter += 1;
            await this.broker.cacher.set(this.keyPrefix + key, counter, this.clearPeriod / 1000);
            return counter;
        }

        return this.memoryStore.inc(key);
    }
}
thib3113 commented 1 year ago

Please don't upgrade dependencies because it can cause breaking changes (E.g. jest 29 doesn't support Node 10, but the current moleculer-web version should support it.)

npm failed to resolve dependencies, thats why I updated them . But, it seems that updating eslint-plugin-promise is enough ( eslint-plugin-promise@5.2.0 ask for eslint@^7.0.0 )