nestjs-rate-limiter
Advanced tools
Comparing version 2.7.0 to 2.7.1
@@ -28,4 +28,6 @@ "use strict"; | ||
maxQueueSize: 100, | ||
omitResponseHeaders: false, | ||
errorMessage: 'Rate limit exceeded', | ||
customResponseSchema: undefined | ||
customResponseSchema: undefined, | ||
logger: true | ||
}; |
@@ -40,2 +40,3 @@ "use strict"; | ||
expect(default_options_1.defaultRateLimiterOptions.maxQueueSize).toBe(100); | ||
expect(default_options_1.defaultRateLimiterOptions.omitResponseHeaders).toBe(false); | ||
expect(default_options_1.defaultRateLimiterOptions.errorMessage).toBe('Rate limit exceeded'); | ||
@@ -42,0 +43,0 @@ expect(default_options_1.defaultRateLimiterOptions.customResponseSchema).toBeUndefined(); |
@@ -9,3 +9,3 @@ import { Reflector } from '@nestjs/core'; | ||
private rateLimiters; | ||
private spesificOptions; | ||
private specificOptions; | ||
private queueLimiter; | ||
@@ -16,3 +16,4 @@ constructor(options: RateLimiterOptions, reflector: Reflector); | ||
private httpHandler; | ||
private setResponseHeaders; | ||
private responseHandler; | ||
} |
@@ -47,7 +47,7 @@ "use strict"; | ||
getRateLimiter(options) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.options = Object.assign(Object.assign({}, default_options_1.defaultRateLimiterOptions), this.options); | ||
this.spesificOptions = null; | ||
this.spesificOptions = options; | ||
this.specificOptions = null; | ||
this.specificOptions = options; | ||
const limiterOptions = Object.assign(Object.assign({}, this.options), options); | ||
@@ -59,14 +59,21 @@ const libraryArguments = __rest(limiterOptions, []); | ||
if (!rateLimiter) { | ||
switch (((_a = this.spesificOptions) === null || _a === void 0 ? void 0 : _a.type) || this.options.type) { | ||
const logger = ((_a = this.specificOptions) === null || _a === void 0 ? void 0 : _a.logger) || this.options.logger; | ||
switch (((_b = this.specificOptions) === null || _b === void 0 ? void 0 : _b.type) || this.options.type) { | ||
case 'Memory': | ||
rateLimiter = new rate_limiter_flexible_1.RateLimiterMemory(libraryArguments); | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMemory'); | ||
if (logger) { | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMemory'); | ||
} | ||
break; | ||
case 'Redis': | ||
rateLimiter = new rate_limiter_flexible_1.RateLimiterRedis(libraryArguments); | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterRedis'); | ||
if (logger) { | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterRedis'); | ||
} | ||
break; | ||
case 'Memcache': | ||
rateLimiter = new rate_limiter_flexible_1.RateLimiterMemcache(libraryArguments); | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMemcache'); | ||
if (logger) { | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMemcache'); | ||
} | ||
break; | ||
@@ -76,5 +83,5 @@ case 'Postgres': | ||
libraryArguments.storeType = this.options.storeClient.constructor.name; | ||
libraryArguments.tableName = ((_b = this.spesificOptions) === null || _b === void 0 ? void 0 : _b.tableName) || this.options.tableName; | ||
libraryArguments.tableName = ((_c = this.specificOptions) === null || _c === void 0 ? void 0 : _c.tableName) || this.options.tableName; | ||
if (libraryArguments.tableName === undefined) { | ||
libraryArguments.tableName = ((_c = this.spesificOptions) === null || _c === void 0 ? void 0 : _c.keyPrefix) || this.options.keyPrefix; | ||
libraryArguments.tableName = ((_d = this.specificOptions) === null || _d === void 0 ? void 0 : _d.keyPrefix) || this.options.keyPrefix; | ||
} | ||
@@ -95,3 +102,5 @@ if (libraryArguments.tableCreated === undefined) | ||
}); | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterPostgres'); | ||
if (logger) { | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterPostgres'); | ||
} | ||
break; | ||
@@ -101,5 +110,5 @@ case 'MySQL': | ||
libraryArguments.storeType = this.options.storeClient.constructor.name; | ||
libraryArguments.tableName = ((_d = this.spesificOptions) === null || _d === void 0 ? void 0 : _d.tableName) || this.options.tableName; | ||
libraryArguments.tableName = ((_e = this.specificOptions) === null || _e === void 0 ? void 0 : _e.tableName) || this.options.tableName; | ||
if (libraryArguments.tableName === undefined) { | ||
libraryArguments.tableName = ((_e = this.spesificOptions) === null || _e === void 0 ? void 0 : _e.keyPrefix) || this.options.keyPrefix; | ||
libraryArguments.tableName = ((_f = this.specificOptions) === null || _f === void 0 ? void 0 : _f.keyPrefix) || this.options.keyPrefix; | ||
} | ||
@@ -120,3 +129,5 @@ if (libraryArguments.tableCreated === undefined) | ||
}); | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMySQL'); | ||
if (logger) { | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMySQL'); | ||
} | ||
break; | ||
@@ -126,8 +137,10 @@ case 'Mongo': | ||
libraryArguments.storeType = this.options.storeClient.constructor.name; | ||
libraryArguments.tableName = ((_f = this.spesificOptions) === null || _f === void 0 ? void 0 : _f.tableName) || this.options.tableName; | ||
libraryArguments.tableName = ((_g = this.specificOptions) === null || _g === void 0 ? void 0 : _g.tableName) || this.options.tableName; | ||
if (libraryArguments.tableName === undefined) { | ||
libraryArguments.tableName = ((_g = this.spesificOptions) === null || _g === void 0 ? void 0 : _g.keyPrefix) || this.options.keyPrefix; | ||
libraryArguments.tableName = ((_h = this.specificOptions) === null || _h === void 0 ? void 0 : _h.keyPrefix) || this.options.keyPrefix; | ||
} | ||
rateLimiter = new rate_limiter_flexible_1.RateLimiterMongo(libraryArguments); | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMongo'); | ||
if (logger) { | ||
common_1.Logger.log(`Rate Limiter started with ${limiterOptions.keyPrefix} key prefix`, 'RateLimiterMongo'); | ||
} | ||
break; | ||
@@ -139,5 +152,5 @@ default: | ||
} | ||
if (((_h = this.spesificOptions) === null || _h === void 0 ? void 0 : _h.queueEnabled) || this.options.queueEnabled) { | ||
if (((_j = this.specificOptions) === null || _j === void 0 ? void 0 : _j.queueEnabled) || this.options.queueEnabled) { | ||
this.queueLimiter = new rate_limiter_flexible_1.RateLimiterQueue(rateLimiter, { | ||
maxQueueSize: ((_j = this.spesificOptions) === null || _j === void 0 ? void 0 : _j.maxQueueSize) || this.options.maxQueueSize | ||
maxQueueSize: ((_k = this.specificOptions) === null || _k === void 0 ? void 0 : _k.maxQueueSize) || this.options.maxQueueSize | ||
}); | ||
@@ -147,4 +160,4 @@ } | ||
limiter: rateLimiter, | ||
whiteList: ((_k = this.spesificOptions) === null || _k === void 0 ? void 0 : _k.whiteList) || this.options.whiteList, | ||
blackList: ((_l = this.spesificOptions) === null || _l === void 0 ? void 0 : _l.blackList) || this.options.blackList, | ||
whiteList: ((_l = this.specificOptions) === null || _l === void 0 ? void 0 : _l.whiteList) || this.options.whiteList, | ||
blackList: ((_m = this.specificOptions) === null || _m === void 0 ? void 0 : _m.blackList) || this.options.blackList, | ||
runActionAnyway: false | ||
@@ -158,4 +171,4 @@ }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let points = ((_a = this.spesificOptions) === null || _a === void 0 ? void 0 : _a.points) || this.options.points; | ||
let pointsConsumed = ((_b = this.spesificOptions) === null || _b === void 0 ? void 0 : _b.pointsConsumed) || this.options.pointsConsumed; | ||
let points = ((_a = this.specificOptions) === null || _a === void 0 ? void 0 : _a.points) || this.options.points; | ||
let pointsConsumed = ((_b = this.specificOptions) === null || _b === void 0 ? void 0 : _b.pointsConsumed) || this.options.pointsConsumed; | ||
const reflectedOptions = this.reflector.get('rateLimit', context.getHandler()); | ||
@@ -198,14 +211,20 @@ if (reflectedOptions) { | ||
} | ||
setResponseHeaders(response, points, rateLimiterResponse) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
response.header('Retry-After', Math.ceil(rateLimiterResponse.msBeforeNext / 1000)); | ||
response.header('X-RateLimit-Limit', points); | ||
response.header('X-Retry-Remaining', rateLimiterResponse.remainingPoints); | ||
response.header('X-Retry-Reset', new Date(Date.now() + rateLimiterResponse.msBeforeNext).toUTCString()); | ||
}); | ||
} | ||
responseHandler(response, key, rateLimiter, points, pointsConsumed) { | ||
var _a, _b, _c, _d; | ||
var _a, _b, _c, _d, _e; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
if (((_a = this.spesificOptions) === null || _a === void 0 ? void 0 : _a.queueEnabled) || this.options.queueEnabled) | ||
if (((_a = this.specificOptions) === null || _a === void 0 ? void 0 : _a.queueEnabled) || this.options.queueEnabled) | ||
yield this.queueLimiter.removeTokens(1); | ||
else { | ||
const rateLimiterResponse = yield rateLimiter.consume(key, pointsConsumed); | ||
response.header('Retry-After', Math.ceil(rateLimiterResponse.msBeforeNext / 1000)); | ||
response.header('X-RateLimit-Limit', points); | ||
response.header('X-Retry-Remaining', rateLimiterResponse.remainingPoints); | ||
response.header('X-Retry-Reset', new Date(Date.now() + rateLimiterResponse.msBeforeNext).toUTCString()); | ||
if (!((_b = this.specificOptions) === null || _b === void 0 ? void 0 : _b.omitResponseHeaders) && !this.options.omitResponseHeaders) | ||
this.setResponseHeaders(response, points, rateLimiterResponse); | ||
} | ||
@@ -215,8 +234,8 @@ } | ||
response.header('Retry-After', Math.ceil(rateLimiterResponse.msBeforeNext / 1000)); | ||
if (typeof ((_b = this.spesificOptions) === null || _b === void 0 ? void 0 : _b.customResponseSchema) === 'function' || typeof this.options.customResponseSchema === 'function') { | ||
var errorBody = ((_c = this.spesificOptions) === null || _c === void 0 ? void 0 : _c.customResponseSchema) || this.options.customResponseSchema; | ||
if (typeof ((_c = this.specificOptions) === null || _c === void 0 ? void 0 : _c.customResponseSchema) === 'function' || typeof this.options.customResponseSchema === 'function') { | ||
var errorBody = ((_d = this.specificOptions) === null || _d === void 0 ? void 0 : _d.customResponseSchema) || this.options.customResponseSchema; | ||
throw new common_1.HttpException(errorBody(rateLimiterResponse), common_1.HttpStatus.TOO_MANY_REQUESTS); | ||
} | ||
else { | ||
throw new common_1.HttpException(((_d = this.spesificOptions) === null || _d === void 0 ? void 0 : _d.errorMessage) || this.options.errorMessage, common_1.HttpStatus.TOO_MANY_REQUESTS); | ||
throw new common_1.HttpException(((_e = this.specificOptions) === null || _e === void 0 ? void 0 : _e.errorMessage) || this.options.errorMessage, common_1.HttpStatus.TOO_MANY_REQUESTS); | ||
} | ||
@@ -223,0 +242,0 @@ } |
@@ -28,3 +28,5 @@ import { Provider } from '@nestjs/common'; | ||
maxQueueSize?: number; | ||
omitResponseHeaders?: boolean; | ||
errorMessage?: string; | ||
logger?: boolean; | ||
customResponseSchema?: (rateLimiterResponse: RateLimiterRes) => {}; | ||
@@ -31,0 +33,0 @@ } |
{ | ||
"name": "nestjs-rate-limiter", | ||
"version": "2.7.0", | ||
"version": "2.7.1", | ||
"description": "Highly configurable rate limiter library", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -48,3 +48,5 @@ <p align="center"> | ||
- [maxQueueSize](https://github.com/ozkanonur/nestjs-rate-limiter#-maxQueueSize) | ||
- [omitResponseHeaders](https://github.com/ozkanonur/nestjs-rate-limiter#-omitResponseHeaders) | ||
- [errorMessage](https://github.com/ozkanonur/nestjs-rate-limiter#-errorMessage) | ||
- [customResponseSchema](https://github.com/ozkanonur/nestjs-rate-limiter#-customResponseSchema) | ||
- [Benchmarks](https://github.com/ozkanonur/nestjs-rate-limiter#benchmarks) | ||
@@ -195,3 +197,5 @@ - [TODO List](https://github.com/ozkanonur/nestjs-rate-limiter#todo) | ||
maxQueueSize: 100, | ||
omitResponseHeaders: false, | ||
errorMessage: 'Rate limit exceeded', | ||
logger: true, | ||
customResponseSchema: undefined | ||
@@ -434,2 +438,11 @@ }), | ||
#### ● omitResponseHeaders | ||
<code> Default: false</code> | ||
<br> | ||
<code> Type: boolean</code> | ||
<br> | ||
Whether or not the rate limit headers (<code>X-Retry-After</code>, <code>X-RateLimit-Limit</code>, <code>X-Retry-Remaining</code>, <code>X-Retry-Reset</code>) should be omitted in the response. | ||
#### ● errorMessage | ||
@@ -443,2 +456,10 @@ <code> Default: 'Rate limit exceeded'</code> | ||
#### ● logger | ||
<code> Default: true</code> | ||
<br> | ||
<code> Type: boolean</code> | ||
<br> | ||
logger option allows to enable or disable logging from library. | ||
#### ● customResponseSchema | ||
@@ -470,5 +491,4 @@ <code> Default: undefined </code> | ||
## TODO | ||
- [ ] Create example projects for each technology | ||
- [ ] Support Websocket | ||
- [ ] Support Rpc | ||
- [ ] Tests & Github Actions (for automatic npm deployment on master branch) | ||
- [ ] Github Actions |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
54054
644
490