@golemio/core 4.1.3-dev.2897104315 → 4.1.3-dev.2923558338
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers/rate-limit/IRateLimitOptions.d.ts +10 -0
- package/dist/helpers/rate-limit/IRateLimitOptions.js +3 -0
- package/dist/helpers/rate-limit/IRateLimitOptions.js.map +1 -0
- package/dist/helpers/rate-limit/RateLimitMiddleware.d.ts +4 -0
- package/dist/helpers/rate-limit/RateLimitMiddleware.js +60 -0
- package/dist/helpers/rate-limit/RateLimitMiddleware.js.map +1 -0
- package/dist/helpers/rate-limit/index.d.ts +2 -0
- package/dist/helpers/rate-limit/index.js +6 -0
- package/dist/helpers/rate-limit/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Request } from "express";
|
|
2
|
+
export interface IRateLimitOptions {
|
|
3
|
+
keyPrefix: string;
|
|
4
|
+
points: number;
|
|
5
|
+
durationSeconds: number;
|
|
6
|
+
blockDurationSeconds?: number;
|
|
7
|
+
inMemoryBlockOnConsumed?: number;
|
|
8
|
+
storeClient?: unknown;
|
|
9
|
+
getKey?: (req: Request) => string;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IRateLimitOptions.js","sourceRoot":"","sources":["../../../src/helpers/rate-limit/IRateLimitOptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRateLimitMiddleware = void 0;
|
|
4
|
+
const errors_1 = require("@golemio/errors");
|
|
5
|
+
const rate_limiter_flexible_1 = require("rate-limiter-flexible");
|
|
6
|
+
const MODULE_NAME = "RateLimitMiddleware";
|
|
7
|
+
const MILLISECONDS_IN_SECOND = 1000;
|
|
8
|
+
const UNKNOWN_CLIENT_KEY = "unknown";
|
|
9
|
+
const resolveDefaultKey = (req) => req.ip || req.socket.remoteAddress || UNKNOWN_CLIENT_KEY;
|
|
10
|
+
const createLimiter = (options, logger) => {
|
|
11
|
+
const baseOptions = {
|
|
12
|
+
keyPrefix: options.keyPrefix,
|
|
13
|
+
points: options.points,
|
|
14
|
+
duration: options.durationSeconds,
|
|
15
|
+
blockDuration: options.blockDurationSeconds ?? 0,
|
|
16
|
+
};
|
|
17
|
+
if (!options.storeClient) {
|
|
18
|
+
logger.warn("No storeClient provided — the rate limit is enforced per process, not globally across replicas.");
|
|
19
|
+
return new rate_limiter_flexible_1.RateLimiterMemory(baseOptions);
|
|
20
|
+
}
|
|
21
|
+
const inMemoryBlockOnConsumed = options.inMemoryBlockOnConsumed ?? options.points;
|
|
22
|
+
if (inMemoryBlockOnConsumed < options.points) {
|
|
23
|
+
throw new errors_1.GeneralError("inMemoryBlockOnConsumed must be greater than or equal to points.", MODULE_NAME);
|
|
24
|
+
}
|
|
25
|
+
return new rate_limiter_flexible_1.RateLimiterRedis({
|
|
26
|
+
...baseOptions,
|
|
27
|
+
storeClient: options.storeClient,
|
|
28
|
+
inMemoryBlockOnConsumed,
|
|
29
|
+
inMemoryBlockDuration: options.durationSeconds,
|
|
30
|
+
insuranceLimiter: new rate_limiter_flexible_1.RateLimiterMemory(baseOptions),
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
const setRateLimitHeaders = (res, points, result) => {
|
|
34
|
+
res.set("X-RateLimit-Limit", String(points));
|
|
35
|
+
res.set("X-RateLimit-Remaining", String(Math.max(result.remainingPoints, 0)));
|
|
36
|
+
res.set("X-RateLimit-Reset", String(Math.ceil((Date.now() + result.msBeforeNext) / MILLISECONDS_IN_SECOND)));
|
|
37
|
+
};
|
|
38
|
+
const createRateLimitMiddleware = (options, logger) => {
|
|
39
|
+
const limiter = createLimiter(options, logger);
|
|
40
|
+
const getKey = options.getKey ?? resolveDefaultKey;
|
|
41
|
+
return async (req, res, next) => {
|
|
42
|
+
try {
|
|
43
|
+
const result = await limiter.consume(getKey(req), 1);
|
|
44
|
+
setRateLimitHeaders(res, options.points, result);
|
|
45
|
+
next();
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (err instanceof rate_limiter_flexible_1.RateLimiterRes) {
|
|
49
|
+
setRateLimitHeaders(res, options.points, err);
|
|
50
|
+
res.set("Retry-After", String(Math.ceil(err.msBeforeNext / MILLISECONDS_IN_SECOND)));
|
|
51
|
+
next(new errors_1.GeneralError("Too many requests.", MODULE_NAME, undefined, 429));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
logger.error(new errors_1.GeneralError("Rate limit check failed, the request is allowed.", MODULE_NAME, err));
|
|
55
|
+
next();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
exports.createRateLimitMiddleware = createRateLimitMiddleware;
|
|
60
|
+
//# sourceMappingURL=RateLimitMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RateLimitMiddleware.js","sourceRoot":"","sources":["../../../src/helpers/rate-limit/RateLimitMiddleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRateLimitMiddleware = void 0;
|
|
4
|
+
var RateLimitMiddleware_1 = require("./RateLimitMiddleware");
|
|
5
|
+
Object.defineProperty(exports, "createRateLimitMiddleware", { enumerable: true, get: function () { return RateLimitMiddleware_1.createRateLimitMiddleware; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/helpers/rate-limit/index.ts"],"names":[],"mappings":";;;AAAA,6DAAkE;AAAzD,gIAAA,yBAAyB,OAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export * as OutputGateway from "./output-gateway/index";
|
|
|
4
4
|
export * as SchemaDefinitions from "./schema-definitions/index";
|
|
5
5
|
export * as AzureHelpers from "./helpers/data-access/azure/index";
|
|
6
6
|
export * as OpenSearchHelpers from "./helpers/data-access/opensearch/index";
|
|
7
|
+
export * as RateLimitHelpers from "./helpers/rate-limit/index";
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.OpenSearchHelpers = exports.AzureHelpers = exports.SchemaDefinitions = exports.OutputGateway = exports.IntegrationEngine = exports.InputGateway = void 0;
|
|
36
|
+
exports.RateLimitHelpers = exports.OpenSearchHelpers = exports.AzureHelpers = exports.SchemaDefinitions = exports.OutputGateway = exports.IntegrationEngine = exports.InputGateway = void 0;
|
|
37
37
|
// Library exports
|
|
38
38
|
exports.InputGateway = __importStar(require("./input-gateway/index"));
|
|
39
39
|
exports.IntegrationEngine = __importStar(require("./integration-engine/index"));
|
|
@@ -41,4 +41,5 @@ exports.OutputGateway = __importStar(require("./output-gateway/index"));
|
|
|
41
41
|
exports.SchemaDefinitions = __importStar(require("./schema-definitions/index"));
|
|
42
42
|
exports.AzureHelpers = __importStar(require("./helpers/data-access/azure/index"));
|
|
43
43
|
exports.OpenSearchHelpers = __importStar(require("./helpers/data-access/opensearch/index"));
|
|
44
|
+
exports.RateLimitHelpers = __importStar(require("./helpers/rate-limit/index"));
|
|
44
45
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kBAAkB;AAClB,sEAA0C;AAC1C,gFAA+C;AAC/C,wEAA2C;AAC3C,gFAAgD;AAChD,kFAAiE;AACjE,4FAA2E"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kBAAkB;AAClB,sEAA0C;AAC1C,gFAA+C;AAC/C,wEAA2C;AAC3C,gFAAgD;AAChD,kFAAiE;AACjE,4FAA2E;AAC3E,+EAA8D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@golemio/core",
|
|
3
|
-
"version": "4.1.3-dev.
|
|
3
|
+
"version": "4.1.3-dev.2923558338",
|
|
4
4
|
"description": "Golemio Core Module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -119,6 +119,7 @@
|
|
|
119
119
|
"pino-pretty": "^10.3.1",
|
|
120
120
|
"prom-client": "^14.0.0",
|
|
121
121
|
"qs": "^6.14.1",
|
|
122
|
+
"rate-limiter-flexible": "^11.2.1",
|
|
122
123
|
"redis-rstream": "^1.0.1",
|
|
123
124
|
"redis-semaphore": "^5.6.0",
|
|
124
125
|
"redis-wstream": "^1.0.0",
|
|
@@ -132,7 +133,14 @@
|
|
|
132
133
|
"overrides": {
|
|
133
134
|
"fast-uri": "^3.1.8",
|
|
134
135
|
"lightship": {
|
|
135
|
-
"fastify": "^5.8.5"
|
|
136
|
+
"fastify": "^5.8.5",
|
|
137
|
+
"fast-uri": "^3.1.8"
|
|
138
|
+
},
|
|
139
|
+
"@google-cloud/storage": {
|
|
140
|
+
"fast-xml-builder": "^1.2.0"
|
|
141
|
+
},
|
|
142
|
+
"ajv": {
|
|
143
|
+
"fast-uri": "^3.1.8"
|
|
136
144
|
}
|
|
137
145
|
}
|
|
138
146
|
}
|