@metric-im/administrate 1.0.1 → 1.0.2

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/multisite.mjs CHANGED
@@ -19,6 +19,7 @@ export class MultiSite {
19
19
  this.usedPorts = new Set();
20
20
  this.healthCheckIntervals = new Map();
21
21
  this.isShuttingDown = false;
22
+ this.errorLogTracker = new Map(); // Track error frequency for rate limiting
22
23
  this.setupCleanup();
23
24
  }
24
25
  get spawnPort() {
@@ -176,6 +177,37 @@ export class MultiSite {
176
177
  }
177
178
  });
178
179
  }
180
+
181
+ // Rate limit error logging to prevent spam
182
+ shouldLogError(target, clientIP) {
183
+ const key = `${clientIP}:${target}`;
184
+ const now = Date.now();
185
+ const logEntry = this.errorLogTracker.get(key);
186
+
187
+ if (!logEntry) {
188
+ this.errorLogTracker.set(key, { count: 1, firstSeen: now, lastLogged: now });
189
+ return true;
190
+ }
191
+
192
+ logEntry.count++;
193
+
194
+ // Reset counter if it's been more than 5 minutes since first error
195
+ if (now - logEntry.firstSeen > 300000) {
196
+ logEntry.count = 1;
197
+ logEntry.firstSeen = now;
198
+ logEntry.lastLogged = now;
199
+ return true;
200
+ }
201
+
202
+ // Log first error, then every 10th error, but not more than once per minute
203
+ if (logEntry.count === 1 ||
204
+ (logEntry.count % 10 === 0 && now - logEntry.lastLogged > 60000)) {
205
+ logEntry.lastLogged = now;
206
+ return true;
207
+ }
208
+
209
+ return false;
210
+ }
179
211
  static async attach(app,options) {
180
212
  const instance = new MultiSite(app,options);
181
213
  instance.config = new Config();
@@ -205,6 +237,7 @@ export class MultiSite {
205
237
  const method = req.method;
206
238
  const isBodyMethod = ['POST', 'PUT', 'PATCH'].includes(method);
207
239
  const payload = isBodyMethod ? req.body : null;
240
+ const clientIP = req.ip || req.connection.remoteAddress || req.headers['x-forwarded-for'];
208
241
 
209
242
  // Debug logging for POST requests
210
243
  if (method === 'POST') {
@@ -267,7 +300,15 @@ export class MultiSite {
267
300
  res.status(response.status).set(cleanHeaders).send(response.data);
268
301
  }
269
302
  } catch (error) {
270
- console.error(`[Proxy] Error connecting to ${target}:`, error.message);
303
+ // Rate limit error logging to prevent spam
304
+ if (this.shouldLogError(target, clientIP)) {
305
+ const logEntry = this.errorLogTracker.get(`${clientIP}:${target}`);
306
+ if (logEntry && logEntry.count > 1) {
307
+ console.error(`${clientIP}:E: [Proxy] Error connecting to ${target}: ${error.message} (${logEntry.count} times)`);
308
+ } else {
309
+ console.error(`${clientIP}:E: [Proxy] Error connecting to ${target}: ${error.message}`);
310
+ }
311
+ }
271
312
 
272
313
  // // Clean up dead processes
273
314
  // this.removeDeadSites();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metric-im/administrate",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Tools for site administration",
5
5
  "homepage": "https://github.com/metric-im/administrate#readme",
6
6
  "bugs": {
@@ -1,10 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Read(//home/msprague/workspace/sitewell/**)",
5
- "Read(//home/msprague/workspace/rootz/data-wallet-demos/**)"
6
- ],
7
- "deny": [],
8
- "ask": []
9
- }
10
- }