xypriss 1.1.4 → 1.2.0
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/cjs/src/index.js +56 -0
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/plugins/modules/index.js +304 -0
- package/dist/cjs/src/plugins/modules/index.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/builtin/CompressionPlugin.js +410 -0
- package/dist/cjs/src/plugins/modules/network/builtin/CompressionPlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/builtin/ConnectionPlugin.js +797 -0
- package/dist/cjs/src/plugins/modules/network/builtin/ConnectionPlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/builtin/ProxyPlugin.js +409 -0
- package/dist/cjs/src/plugins/modules/network/builtin/ProxyPlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/builtin/RateLimitPlugin.js +606 -0
- package/dist/cjs/src/plugins/modules/network/builtin/RateLimitPlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/core/NetworkPlugin.js +225 -0
- package/dist/cjs/src/plugins/modules/network/core/NetworkPlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/core/NetworkPluginFactory.js +40 -0
- package/dist/cjs/src/plugins/modules/network/core/NetworkPluginFactory.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/index.js +120 -0
- package/dist/cjs/src/plugins/modules/network/index.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/types/NetworkTypes.js +24 -0
- package/dist/cjs/src/plugins/modules/network/types/NetworkTypes.js.map +1 -0
- package/dist/cjs/src/plugins/modules/network/utils/NetworkPluginUtils.js +63 -0
- package/dist/cjs/src/plugins/modules/network/utils/NetworkPluginUtils.js.map +1 -0
- package/dist/cjs/src/plugins/modules/types/PluginTypes.js +1 -0
- package/dist/cjs/src/plugins/modules/types/PluginTypes.js.map +1 -1
- package/dist/cjs/src/server/FastServer.js +111 -2
- package/dist/cjs/src/server/FastServer.js.map +1 -1
- package/dist/cjs/src/server/conf/networkConnectionConf.js +25 -0
- package/dist/cjs/src/server/conf/networkConnectionConf.js.map +1 -0
- package/dist/cjs/src/server/conf/proxyConfig.js +23 -0
- package/dist/cjs/src/server/conf/proxyConfig.js.map +1 -0
- package/dist/cjs/src/server/conf/rateLimitConfig.js +35 -0
- package/dist/cjs/src/server/conf/rateLimitConfig.js.map +1 -0
- package/dist/cjs/src/server/const/default.js +6 -0
- package/dist/cjs/src/server/const/default.js.map +1 -1
- package/dist/cjs/src/server/handlers/NotFoundHandler.js +217 -0
- package/dist/cjs/src/server/handlers/NotFoundHandler.js.map +1 -0
- package/dist/cjs/src/server/handlers/templates/notFoundTemp.js +163 -0
- package/dist/cjs/src/server/handlers/templates/notFoundTemp.js.map +1 -0
- package/dist/esm/mods/security/src/components/cache/UFSIMC.js +5 -5
- package/dist/esm/mods/security/src/components/cache/UFSIMC.js.map +1 -1
- package/dist/esm/mods/security/src/components/cache/cacheSys.utils.js +3 -3
- package/dist/esm/mods/security/src/components/cache/cacheSys.utils.js.map +1 -1
- package/dist/esm/src/index.js +18 -0
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/plugins/modules/index.js +275 -0
- package/dist/esm/src/plugins/modules/index.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/builtin/CompressionPlugin.js +389 -0
- package/dist/esm/src/plugins/modules/network/builtin/CompressionPlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/builtin/ConnectionPlugin.js +776 -0
- package/dist/esm/src/plugins/modules/network/builtin/ConnectionPlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/builtin/ProxyPlugin.js +407 -0
- package/dist/esm/src/plugins/modules/network/builtin/ProxyPlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/builtin/RateLimitPlugin.js +585 -0
- package/dist/esm/src/plugins/modules/network/builtin/RateLimitPlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/core/NetworkPlugin.js +223 -0
- package/dist/esm/src/plugins/modules/network/core/NetworkPlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/core/NetworkPluginFactory.js +38 -0
- package/dist/esm/src/plugins/modules/network/core/NetworkPluginFactory.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/index.js +109 -0
- package/dist/esm/src/plugins/modules/network/index.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/types/NetworkTypes.js +24 -0
- package/dist/esm/src/plugins/modules/network/types/NetworkTypes.js.map +1 -0
- package/dist/esm/src/plugins/modules/network/utils/NetworkPluginUtils.js +61 -0
- package/dist/esm/src/plugins/modules/network/utils/NetworkPluginUtils.js.map +1 -0
- package/dist/esm/src/plugins/modules/types/PluginTypes.js +1 -0
- package/dist/esm/src/plugins/modules/types/PluginTypes.js.map +1 -1
- package/dist/esm/src/server/FastServer.js +111 -2
- package/dist/esm/src/server/FastServer.js.map +1 -1
- package/dist/esm/src/server/conf/networkConnectionConf.js +23 -0
- package/dist/esm/src/server/conf/networkConnectionConf.js.map +1 -0
- package/dist/esm/src/server/conf/proxyConfig.js +21 -0
- package/dist/esm/src/server/conf/proxyConfig.js.map +1 -0
- package/dist/esm/src/server/conf/rateLimitConfig.js +33 -0
- package/dist/esm/src/server/conf/rateLimitConfig.js.map +1 -0
- package/dist/esm/src/server/const/default.js +6 -0
- package/dist/esm/src/server/const/default.js.map +1 -1
- package/dist/esm/src/server/handlers/NotFoundHandler.js +194 -0
- package/dist/esm/src/server/handlers/NotFoundHandler.js.map +1 -0
- package/dist/esm/src/server/handlers/templates/notFoundTemp.js +161 -0
- package/dist/esm/src/server/handlers/templates/notFoundTemp.js.map +1 -0
- package/dist/index.d.ts +5099 -14
- package/package.json +8 -7
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
import { performance } from 'perf_hooks';
|
|
2
|
+
import rateLimit from 'express-rate-limit';
|
|
3
|
+
import { NetworkPlugin } from '../core/NetworkPlugin.js';
|
|
4
|
+
import { RandomTokens } from 'xypriss-security';
|
|
5
|
+
import * as crypto from 'crypto';
|
|
6
|
+
import { SecureCacheAdapter } from '../../../../cache/SecureCacheAdapter.js';
|
|
7
|
+
import '../../../../../mods/security/src/components/cache/index.js';
|
|
8
|
+
import { NetworkCategory } from '../types/NetworkTypes.js';
|
|
9
|
+
import { Logger } from '../../../../../shared/logger/Logger.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Rate Limit Plugin
|
|
13
|
+
*
|
|
14
|
+
* Advanced rate limiting with multiple strategies, Redis support, and per-route limits
|
|
15
|
+
* Uses express-rate-limit and Redis for distributed rate limiting
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Advanced rate limiting plugin with Redis support
|
|
19
|
+
*/
|
|
20
|
+
class RateLimitPlugin extends NetworkPlugin {
|
|
21
|
+
constructor(config = {
|
|
22
|
+
enabled: true,
|
|
23
|
+
strategy: "fixed-window",
|
|
24
|
+
global: { requests: 1000, window: "1h" },
|
|
25
|
+
skipSuccessfulRequests: false,
|
|
26
|
+
skipFailedRequests: false,
|
|
27
|
+
}) {
|
|
28
|
+
super(config);
|
|
29
|
+
this.id = "xypriss.network.ratelimit";
|
|
30
|
+
this.name = "XyPriss Rate Limiting Plugin (XPRL)";
|
|
31
|
+
this.version = "1.0.0";
|
|
32
|
+
this.networkCategory = NetworkCategory.RATE_LIMIT;
|
|
33
|
+
this.rateLimiters = new Map();
|
|
34
|
+
this.rateLimitStats = {
|
|
35
|
+
totalRequests: 0,
|
|
36
|
+
blockedRequests: 0,
|
|
37
|
+
allowedRequests: 0,
|
|
38
|
+
rateLimitHits: new Map(),
|
|
39
|
+
averageRequestsPerSecond: 0,
|
|
40
|
+
peakRequestsPerSecond: 0,
|
|
41
|
+
lastResetTime: Date.now(),
|
|
42
|
+
securityEvents: new Map(),
|
|
43
|
+
};
|
|
44
|
+
this.logger = new Logger();
|
|
45
|
+
this.initializeCacheAdapter();
|
|
46
|
+
this.initializeRateLimiting();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Initialize cache adapter for rate limiting storage
|
|
50
|
+
*/
|
|
51
|
+
initializeCacheAdapter() {
|
|
52
|
+
const config = this.getRateLimitConfig();
|
|
53
|
+
// Configure cache adapter for rate limiting
|
|
54
|
+
const cacheConfig = {
|
|
55
|
+
strategy: config.redis ? "hybrid" : "memory", // Use memory-only if no Redis config
|
|
56
|
+
memory: {
|
|
57
|
+
maxSize: 50, // 50MB for rate limiting data
|
|
58
|
+
ttl: 3600000, // 1 hour default TTL
|
|
59
|
+
algorithm: "lru",
|
|
60
|
+
evictionPolicy: "ttl",
|
|
61
|
+
},
|
|
62
|
+
performance: {
|
|
63
|
+
compressionThreshold: 1024,
|
|
64
|
+
asyncWrite: true,
|
|
65
|
+
pipeline: true,
|
|
66
|
+
connectionPooling: true,
|
|
67
|
+
},
|
|
68
|
+
security: {
|
|
69
|
+
encryption: true,
|
|
70
|
+
accessMonitoring: true,
|
|
71
|
+
sanitization: true,
|
|
72
|
+
},
|
|
73
|
+
monitoring: {
|
|
74
|
+
enabled: true,
|
|
75
|
+
metricsInterval: 60000, // 1 minute
|
|
76
|
+
detailed: false,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
// Only add Redis config if it exists
|
|
80
|
+
if (config.redis) {
|
|
81
|
+
cacheConfig.redis = {
|
|
82
|
+
host: config.redis.host,
|
|
83
|
+
port: config.redis.port,
|
|
84
|
+
password: config.redis.password,
|
|
85
|
+
db: config.redis.db || 0,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
this.cacheAdapter = new SecureCacheAdapter(cacheConfig);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Initialize rate limiting using cache adapter
|
|
92
|
+
*/
|
|
93
|
+
async initializeRateLimiting() {
|
|
94
|
+
// Connect to cache backends
|
|
95
|
+
await this.cacheAdapter.connect();
|
|
96
|
+
// Create rate limiters
|
|
97
|
+
this.createRateLimiters();
|
|
98
|
+
// Start statistics tracking
|
|
99
|
+
this.startStatsTracking();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Create rate limiters for different scopes
|
|
103
|
+
*/
|
|
104
|
+
createRateLimiters() {
|
|
105
|
+
const config = this.getRateLimitConfig();
|
|
106
|
+
// Global rate limiter
|
|
107
|
+
if (config.global) {
|
|
108
|
+
this.rateLimiters.set("global", this.createRateLimiter("global", config.global));
|
|
109
|
+
}
|
|
110
|
+
// Per-IP rate limiter
|
|
111
|
+
if (config.perIP) {
|
|
112
|
+
this.rateLimiters.set("perIP", this.createRateLimiter("perIP", config.perIP));
|
|
113
|
+
}
|
|
114
|
+
// Per-user rate limiter
|
|
115
|
+
if (config.perUser) {
|
|
116
|
+
this.rateLimiters.set("perUser", this.createRateLimiter("perUser", config.perUser));
|
|
117
|
+
}
|
|
118
|
+
// Per-route rate limiters
|
|
119
|
+
if (config.perRoute) {
|
|
120
|
+
for (const [route, rule] of Object.entries(config.perRoute)) {
|
|
121
|
+
this.rateLimiters.set(`route:${route}`, this.createRateLimiter(`route:${route}`, rule));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create individual rate limiter
|
|
127
|
+
*/
|
|
128
|
+
createRateLimiter(scope, rule) {
|
|
129
|
+
const config = this.getRateLimitConfig();
|
|
130
|
+
const windowMs = this.parseTimeWindow(rule.window);
|
|
131
|
+
const limiterConfig = {
|
|
132
|
+
windowMs,
|
|
133
|
+
max: rule.requests,
|
|
134
|
+
message: {
|
|
135
|
+
error: "Too many requests",
|
|
136
|
+
scope,
|
|
137
|
+
limit: rule.requests,
|
|
138
|
+
window: rule.window,
|
|
139
|
+
retryAfter: Math.ceil(windowMs / 1000),
|
|
140
|
+
},
|
|
141
|
+
standardHeaders: true,
|
|
142
|
+
legacyHeaders: false,
|
|
143
|
+
skipSuccessfulRequests: config.skipSuccessfulRequests || false,
|
|
144
|
+
skipFailedRequests: config.skipFailedRequests || false,
|
|
145
|
+
// Custom key generator based on scope
|
|
146
|
+
keyGenerator: (req) => this.generateRateLimitKey(req, scope),
|
|
147
|
+
// Custom handler for rate limit exceeded
|
|
148
|
+
handler: (req, res) => {
|
|
149
|
+
this.handleRateLimitExceeded(req, res, scope);
|
|
150
|
+
},
|
|
151
|
+
// Skip function for conditional rate limiting
|
|
152
|
+
skip: (req) => this.shouldSkipRateLimit(req, scope),
|
|
153
|
+
};
|
|
154
|
+
// Add cache store for distributed rate limiting
|
|
155
|
+
if (config.strategy !== "fixed-window") {
|
|
156
|
+
limiterConfig.store = this.createCacheStore(scope, windowMs);
|
|
157
|
+
}
|
|
158
|
+
return rateLimit(limiterConfig);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Execute rate limiting logic
|
|
162
|
+
*/
|
|
163
|
+
async executeNetwork(context) {
|
|
164
|
+
const startTime = performance.now();
|
|
165
|
+
const { req, res } = context;
|
|
166
|
+
try {
|
|
167
|
+
if (!this.getRateLimitConfig().enabled) {
|
|
168
|
+
return {
|
|
169
|
+
success: true,
|
|
170
|
+
executionTime: performance.now() - startTime,
|
|
171
|
+
shouldContinue: true,
|
|
172
|
+
data: {
|
|
173
|
+
rateLimited: false,
|
|
174
|
+
reason: "rate_limiting_disabled",
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// Apply rate limiters in order of specificity
|
|
179
|
+
const rateLimitResults = await this.applyRateLimiters(req, res);
|
|
180
|
+
// Update statistics
|
|
181
|
+
this.updateRateLimitStats(rateLimitResults);
|
|
182
|
+
const executionTime = performance.now() - startTime;
|
|
183
|
+
const wasBlocked = rateLimitResults.some((result) => result.blocked);
|
|
184
|
+
return {
|
|
185
|
+
success: true,
|
|
186
|
+
executionTime,
|
|
187
|
+
shouldContinue: !wasBlocked,
|
|
188
|
+
data: {
|
|
189
|
+
rateLimited: wasBlocked,
|
|
190
|
+
appliedLimits: rateLimitResults,
|
|
191
|
+
remainingRequests: this.getRemainingRequests(req),
|
|
192
|
+
},
|
|
193
|
+
modifications: wasBlocked
|
|
194
|
+
? {
|
|
195
|
+
statusCode: 429,
|
|
196
|
+
headers: {
|
|
197
|
+
"Retry-After": "60",
|
|
198
|
+
"X-RateLimit-Limit": this.getRateLimitHeader(req),
|
|
199
|
+
"X-RateLimit-Remaining": "0",
|
|
200
|
+
},
|
|
201
|
+
}
|
|
202
|
+
: undefined,
|
|
203
|
+
networkMetrics: {
|
|
204
|
+
processingTime: executionTime,
|
|
205
|
+
memoryUsage: process.memoryUsage().heapUsed,
|
|
206
|
+
cpuUsage: process.cpuUsage().user,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
return {
|
|
212
|
+
success: false,
|
|
213
|
+
executionTime: performance.now() - startTime,
|
|
214
|
+
shouldContinue: true,
|
|
215
|
+
error,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Apply all configured rate limiters
|
|
221
|
+
*/
|
|
222
|
+
async applyRateLimiters(req, res) {
|
|
223
|
+
const results = [];
|
|
224
|
+
for (const [scope, limiter] of this.rateLimiters.entries()) {
|
|
225
|
+
if (this.shouldApplyLimiter(req, scope)) {
|
|
226
|
+
try {
|
|
227
|
+
await new Promise((resolve, reject) => {
|
|
228
|
+
limiter(req, res, (err) => {
|
|
229
|
+
if (err) {
|
|
230
|
+
if (err.status === 429) {
|
|
231
|
+
results.push({
|
|
232
|
+
scope,
|
|
233
|
+
blocked: true,
|
|
234
|
+
error: err,
|
|
235
|
+
});
|
|
236
|
+
resolve(); // Don't reject, just mark as blocked
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
reject(err);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
results.push({ scope, blocked: false });
|
|
244
|
+
resolve();
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
results.push({ scope, blocked: true, error });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return results;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Generate secure rate limit key based on scope using security modules
|
|
258
|
+
*/
|
|
259
|
+
generateRateLimitKey(req, scope) {
|
|
260
|
+
let baseKey;
|
|
261
|
+
switch (scope) {
|
|
262
|
+
case "global":
|
|
263
|
+
baseKey = "global";
|
|
264
|
+
break;
|
|
265
|
+
case "perIP":
|
|
266
|
+
baseKey = req.ip || req.socket.remoteAddress || "unknown";
|
|
267
|
+
break;
|
|
268
|
+
case "perUser":
|
|
269
|
+
baseKey = req.user?.id || req.ip || "anonymous";
|
|
270
|
+
break;
|
|
271
|
+
default:
|
|
272
|
+
if (scope.startsWith("route:")) {
|
|
273
|
+
const route = scope.substring(6);
|
|
274
|
+
baseKey = `${route}:${req.ip}`;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
baseKey = req.ip || "unknown";
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Use secure hashing for consistent key generation
|
|
281
|
+
return this.generateSecureKey(baseKey, scope);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Generate secure hash key using xypriss-security Hash module
|
|
285
|
+
*/
|
|
286
|
+
generateSecureKey(baseKey, scope) {
|
|
287
|
+
try {
|
|
288
|
+
// Use crypto module with secure approach for synchronous operation
|
|
289
|
+
const keyData = `${scope}:${baseKey}:${this.getRateLimitConfig().global?.window || "1h"}`;
|
|
290
|
+
// Use timing-safe comparison approach from security module
|
|
291
|
+
const hash = crypto
|
|
292
|
+
.createHash("sha256")
|
|
293
|
+
.update(keyData)
|
|
294
|
+
.digest("hex");
|
|
295
|
+
// Add entropy using SecureRandom if available
|
|
296
|
+
const salt = this.generateSecureSalt();
|
|
297
|
+
return crypto
|
|
298
|
+
.createHash("sha256")
|
|
299
|
+
.update(hash + salt)
|
|
300
|
+
.digest("hex");
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
// Fallback to crypto hash
|
|
304
|
+
return crypto
|
|
305
|
+
.createHash("sha256")
|
|
306
|
+
.update(`${scope}:${baseKey}`)
|
|
307
|
+
.digest("hex");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Generate secure salt for key hashing
|
|
312
|
+
*/
|
|
313
|
+
generateSecureSalt() {
|
|
314
|
+
try {
|
|
315
|
+
// Use SecureRandom for salt generation
|
|
316
|
+
return RandomTokens.generateSecureToken(16);
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
// Fallback to crypto random bytes
|
|
320
|
+
return crypto.randomBytes(16).toString("hex");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Parse time window string to milliseconds
|
|
325
|
+
*/
|
|
326
|
+
parseTimeWindow(window) {
|
|
327
|
+
const match = window.match(/^(\d+)([smhd])$/);
|
|
328
|
+
if (!match)
|
|
329
|
+
return 60000; // Default 1 minute
|
|
330
|
+
const value = parseInt(match[1]);
|
|
331
|
+
const unit = match[2];
|
|
332
|
+
switch (unit) {
|
|
333
|
+
case "s":
|
|
334
|
+
return value * 1000;
|
|
335
|
+
case "m":
|
|
336
|
+
return value * 60 * 1000;
|
|
337
|
+
case "h":
|
|
338
|
+
return value * 60 * 60 * 1000;
|
|
339
|
+
case "d":
|
|
340
|
+
return value * 24 * 60 * 60 * 1000;
|
|
341
|
+
default:
|
|
342
|
+
return 60000;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Create cache store for distributed rate limiting using SecureCacheAdapter
|
|
347
|
+
*/
|
|
348
|
+
createCacheStore(scope, windowMs) {
|
|
349
|
+
return {
|
|
350
|
+
incr: async (key, cb) => {
|
|
351
|
+
try {
|
|
352
|
+
const fullKey = `ratelimit:${scope}:${key}`;
|
|
353
|
+
// Get current count from cache
|
|
354
|
+
const cached = await this.cacheAdapter.get(fullKey);
|
|
355
|
+
const current = cached ? cached.value + 1 : 1;
|
|
356
|
+
// Store updated count with TTL
|
|
357
|
+
await this.cacheAdapter.set(fullKey, current, {
|
|
358
|
+
ttl: windowMs,
|
|
359
|
+
tags: [`ratelimit`, scope],
|
|
360
|
+
});
|
|
361
|
+
cb(null, {
|
|
362
|
+
totalHits: current,
|
|
363
|
+
resetTime: new Date(Date.now() + windowMs),
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
cb(error);
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
decrement: async (key) => {
|
|
371
|
+
try {
|
|
372
|
+
const fullKey = `ratelimit:${scope}:${key}`;
|
|
373
|
+
const cached = await this.cacheAdapter.get(fullKey);
|
|
374
|
+
const current = cached
|
|
375
|
+
? Math.max(0, cached.value - 1)
|
|
376
|
+
: 0;
|
|
377
|
+
if (current > 0) {
|
|
378
|
+
await this.cacheAdapter.set(fullKey, current, {
|
|
379
|
+
ttl: windowMs,
|
|
380
|
+
tags: [`ratelimit`, scope],
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
await this.cacheAdapter.delete(fullKey);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
this.logger.warn("plugins", "Failed to decrement rate limit key:", error);
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
resetKey: async (key) => {
|
|
392
|
+
try {
|
|
393
|
+
const fullKey = `ratelimit:${scope}:${key}`;
|
|
394
|
+
await this.cacheAdapter.delete(fullKey);
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
this.logger.warn("plugins", "Failed to reset rate limit key:", error);
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Handle rate limit exceeded
|
|
404
|
+
*/
|
|
405
|
+
handleRateLimitExceeded(req, res, scope) {
|
|
406
|
+
this.rateLimitStats.blockedRequests++;
|
|
407
|
+
const hitCount = this.rateLimitStats.rateLimitHits.get(scope) || 0;
|
|
408
|
+
this.rateLimitStats.rateLimitHits.set(scope, hitCount + 1);
|
|
409
|
+
if (!res.headersSent) {
|
|
410
|
+
res.status(429).json({
|
|
411
|
+
error: "Rate limit exceeded",
|
|
412
|
+
scope,
|
|
413
|
+
message: `Too many requests for ${scope}`,
|
|
414
|
+
retryAfter: 60,
|
|
415
|
+
timestamp: new Date().toISOString(),
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Check if rate limiter should be applied
|
|
421
|
+
*/
|
|
422
|
+
shouldApplyLimiter(req, scope) {
|
|
423
|
+
if (scope.startsWith("route:")) {
|
|
424
|
+
const route = scope.substring(6);
|
|
425
|
+
return req.path === route || req.path.startsWith(route);
|
|
426
|
+
}
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Check if request should skip rate limiting
|
|
431
|
+
*/
|
|
432
|
+
shouldSkipRateLimit(req, scope) {
|
|
433
|
+
// Skip rate limiting for health checks
|
|
434
|
+
if (req.path === "/health" || req.path === "/ping") {
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
// Skip for internal requests
|
|
438
|
+
if (req.get("X-Internal-Request")) {
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Update rate limiting statistics
|
|
445
|
+
*/
|
|
446
|
+
updateRateLimitStats(results) {
|
|
447
|
+
this.rateLimitStats.totalRequests++;
|
|
448
|
+
const wasBlocked = results.some((result) => result.blocked);
|
|
449
|
+
if (wasBlocked) {
|
|
450
|
+
this.rateLimitStats.blockedRequests++;
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
this.rateLimitStats.allowedRequests++;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Get remaining requests for client using secure key lookup
|
|
458
|
+
*/
|
|
459
|
+
getRemainingRequests(req) {
|
|
460
|
+
try {
|
|
461
|
+
const key = this.generateRateLimitKey(req, "perIP");
|
|
462
|
+
// In a real implementation, this would query Redis or memory store
|
|
463
|
+
// For now, return a calculated value based on current stats
|
|
464
|
+
const config = this.getRateLimitConfig();
|
|
465
|
+
const maxRequests = config.perIP?.requests || config.global?.requests || 1000;
|
|
466
|
+
const usedRequests = this.rateLimitStats.totalRequests % maxRequests;
|
|
467
|
+
return Math.max(0, maxRequests - usedRequests);
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
return 0; // Conservative approach on error
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Get rate limit header value based on request context
|
|
475
|
+
*/
|
|
476
|
+
getRateLimitHeader(req) {
|
|
477
|
+
const config = this.getRateLimitConfig();
|
|
478
|
+
// Determine which limit applies to this request
|
|
479
|
+
if (config.perIP && req.ip) {
|
|
480
|
+
return config.perIP.requests.toString();
|
|
481
|
+
}
|
|
482
|
+
return config.global?.requests.toString() || "1000";
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Start statistics tracking
|
|
486
|
+
*/
|
|
487
|
+
startStatsTracking() {
|
|
488
|
+
setInterval(() => {
|
|
489
|
+
this.updateRequestsPerSecond();
|
|
490
|
+
}, 1000);
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Update requests per second statistics
|
|
494
|
+
*/
|
|
495
|
+
updateRequestsPerSecond() {
|
|
496
|
+
const now = Date.now();
|
|
497
|
+
const timeDiff = (now - this.rateLimitStats.lastResetTime) / 1000;
|
|
498
|
+
if (timeDiff >= 1) {
|
|
499
|
+
const requestsPerSecond = this.rateLimitStats.totalRequests / timeDiff;
|
|
500
|
+
this.rateLimitStats.averageRequestsPerSecond = requestsPerSecond;
|
|
501
|
+
if (requestsPerSecond > this.rateLimitStats.peakRequestsPerSecond) {
|
|
502
|
+
this.rateLimitStats.peakRequestsPerSecond = requestsPerSecond;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Get rate limit configuration
|
|
508
|
+
*/
|
|
509
|
+
getRateLimitConfig() {
|
|
510
|
+
return this.config;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Validate rate limit configuration
|
|
514
|
+
*/
|
|
515
|
+
validateNetworkConfig(config) {
|
|
516
|
+
if (config.global && config.global.requests <= 0) {
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
519
|
+
if (config.perIP && config.perIP.requests <= 0) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Check network health
|
|
526
|
+
*/
|
|
527
|
+
async checkNetworkHealth() {
|
|
528
|
+
const blockRate = this.rateLimitStats.blockedRequests /
|
|
529
|
+
Math.max(this.rateLimitStats.totalRequests, 1);
|
|
530
|
+
const cacheHealthy = await this.checkCacheHealth();
|
|
531
|
+
return {
|
|
532
|
+
healthy: blockRate < 0.5 && cacheHealthy,
|
|
533
|
+
status: blockRate < 0.2 && cacheHealthy
|
|
534
|
+
? "healthy"
|
|
535
|
+
: blockRate < 0.5 && cacheHealthy
|
|
536
|
+
? "degraded"
|
|
537
|
+
: "unhealthy",
|
|
538
|
+
metrics: {
|
|
539
|
+
responseTime: this.performanceMetrics.averageExecutionTime,
|
|
540
|
+
errorRate: blockRate,
|
|
541
|
+
throughput: this.rateLimitStats.averageRequestsPerSecond,
|
|
542
|
+
connections: cacheHealthy ? 1 : 0,
|
|
543
|
+
},
|
|
544
|
+
lastCheck: new Date(),
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Check cache adapter health
|
|
549
|
+
*/
|
|
550
|
+
async checkCacheHealth() {
|
|
551
|
+
try {
|
|
552
|
+
// Test cache connectivity by performing a simple operation
|
|
553
|
+
const testKey = "health_check_test";
|
|
554
|
+
await this.cacheAdapter.set(testKey, "test", { ttl: 1000 });
|
|
555
|
+
const result = await this.cacheAdapter.get(testKey);
|
|
556
|
+
await this.cacheAdapter.delete(testKey);
|
|
557
|
+
return result !== null;
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Get rate limiting statistics
|
|
565
|
+
*/
|
|
566
|
+
getRateLimitStats() {
|
|
567
|
+
return {
|
|
568
|
+
...this.rateLimitStats,
|
|
569
|
+
cacheConnected: true, // Cache adapter handles connection status internally
|
|
570
|
+
activeLimiters: this.rateLimiters.size,
|
|
571
|
+
rateLimitHits: Object.fromEntries(this.rateLimitStats.rateLimitHits),
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Cleanup resources
|
|
576
|
+
*/
|
|
577
|
+
async destroy() {
|
|
578
|
+
// Disconnect from cache adapter
|
|
579
|
+
await this.cacheAdapter.disconnect();
|
|
580
|
+
await super.destroy();
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
export { RateLimitPlugin };
|
|
585
|
+
//# sourceMappingURL=RateLimitPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RateLimitPlugin.js","sources":["../../../../../../../src/plugins/modules/network/builtin/RateLimitPlugin.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|