@mblaney/holster 1.0.15 → 1.0.16
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/build/holster.js +3 -3
- package/build/holster.js.map +3 -3
- package/package.json +1 -1
- package/src/wire.js +27 -44
package/package.json
CHANGED
package/src/wire.js
CHANGED
|
@@ -13,13 +13,11 @@ if (typeof globalThis.WebSocket === "undefined") {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
// Rate limiting with throttling
|
|
16
|
-
const createRateLimiter =
|
|
16
|
+
const createRateLimiter = isTestEnv => {
|
|
17
17
|
const clients = new Map()
|
|
18
|
-
const maxRequests =
|
|
19
|
-
const windowMs =
|
|
20
|
-
const disconnectThreshold =
|
|
21
|
-
// Check if test environment (mock-socket usage)
|
|
22
|
-
const isTestEnv = opt.wss && opt.wss.constructor.name === "Server"
|
|
18
|
+
const maxRequests = 300 // 5 requests per second
|
|
19
|
+
const windowMs = 60000 // 1 minute window
|
|
20
|
+
const disconnectThreshold = 10 // Disconnect after 10 violations
|
|
23
21
|
let cleanupInterval = null
|
|
24
22
|
|
|
25
23
|
const cleanup = () => {
|
|
@@ -191,7 +189,9 @@ const Wire = opt => {
|
|
|
191
189
|
}
|
|
192
190
|
|
|
193
191
|
// Initialize rate limiting and connection management
|
|
194
|
-
|
|
192
|
+
// Check if test environment (mock-socket usage)
|
|
193
|
+
const isTestEnv = opt.wss && opt.wss.constructor.name === "Server"
|
|
194
|
+
const rateLimiter = createRateLimiter(isTestEnv)
|
|
195
195
|
const connectionManager = createConnectionManager(opt.maxConnections || 1000)
|
|
196
196
|
|
|
197
197
|
// The check function is required because user data must provide a public key
|
|
@@ -463,9 +463,7 @@ const Wire = opt => {
|
|
|
463
463
|
|
|
464
464
|
// Generate unique client ID for rate limiting
|
|
465
465
|
const clientId = utils.text.random(9)
|
|
466
|
-
console.log(
|
|
467
|
-
`[HOLSTER-CONNECT] New WebSocket client connected: ${clientId}`,
|
|
468
|
-
)
|
|
466
|
+
console.log(`New WebSocket client connected: ${clientId}`)
|
|
469
467
|
|
|
470
468
|
ws.on("error", error => {
|
|
471
469
|
console.log("WebSocket error:", error)
|
|
@@ -473,9 +471,7 @@ const Wire = opt => {
|
|
|
473
471
|
})
|
|
474
472
|
|
|
475
473
|
ws.on("close", () => {
|
|
476
|
-
console.log(
|
|
477
|
-
`[HOLSTER-DISCONNECT] WebSocket client disconnected: ${clientId}`,
|
|
478
|
-
)
|
|
474
|
+
console.log(`WebSocket client disconnected: ${clientId}`)
|
|
479
475
|
connectionManager.remove(ws)
|
|
480
476
|
})
|
|
481
477
|
|
|
@@ -505,14 +501,14 @@ const Wire = opt => {
|
|
|
505
501
|
if (delay > 0) {
|
|
506
502
|
const throttleCount = rateLimiter.getThrottleCount(clientId)
|
|
507
503
|
console.log(
|
|
508
|
-
`
|
|
504
|
+
`Client ${clientId}: rate limit exceeded, delay would be ${delay}ms, dropping message (throttle count: ${throttleCount})`,
|
|
509
505
|
)
|
|
510
506
|
// Check if we should disconnect the bad actor
|
|
511
507
|
if (rateLimiter.shouldDisconnect(clientId)) {
|
|
512
508
|
console.log(
|
|
513
|
-
`
|
|
509
|
+
`Client ${clientId}: Disconnecting after ${throttleCount} throttle violations`,
|
|
514
510
|
)
|
|
515
|
-
ws.close(1008, "Rate limit violations
|
|
511
|
+
ws.close(1008, "Rate limit violations")
|
|
516
512
|
return
|
|
517
513
|
}
|
|
518
514
|
|
|
@@ -565,7 +561,7 @@ const Wire = opt => {
|
|
|
565
561
|
let throttleUntil = 0
|
|
566
562
|
let messageQueue = []
|
|
567
563
|
let queueProcessor = null
|
|
568
|
-
const maxQueueLength = opt.maxQueueLength ||
|
|
564
|
+
const maxQueueLength = opt.maxQueueLength || 10000
|
|
569
565
|
|
|
570
566
|
const processQueue = () => {
|
|
571
567
|
if (messageQueue.length === 0) {
|
|
@@ -585,9 +581,7 @@ const Wire = opt => {
|
|
|
585
581
|
|
|
586
582
|
// Throttle period ended, resume processing
|
|
587
583
|
if (clientThrottled && now >= throttleUntil) {
|
|
588
|
-
console.log(
|
|
589
|
-
`[CLIENT-THROTTLED] Throttle period ended, resuming queue processing`,
|
|
590
|
-
)
|
|
584
|
+
console.log(`Throttle period ended, resuming queue processing`)
|
|
591
585
|
clientThrottled = false
|
|
592
586
|
throttleUntil = 0
|
|
593
587
|
}
|
|
@@ -598,8 +592,8 @@ const Wire = opt => {
|
|
|
598
592
|
|
|
599
593
|
// Schedule processing of next message if queue not empty
|
|
600
594
|
if (messageQueue.length > 0) {
|
|
601
|
-
// Add
|
|
602
|
-
queueProcessor = setTimeout(processQueue,
|
|
595
|
+
// Add delay between messages to respect rate limits (300 req/min = 200ms)
|
|
596
|
+
queueProcessor = setTimeout(processQueue, 250)
|
|
603
597
|
} else {
|
|
604
598
|
queueProcessor = null
|
|
605
599
|
}
|
|
@@ -629,30 +623,19 @@ const Wire = opt => {
|
|
|
629
623
|
}
|
|
630
624
|
|
|
631
625
|
const send = data => {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
queueLength: messageQueue.length,
|
|
638
|
-
maxQueueLength: maxQueueLength,
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// Add message to queue instead of sending immediately
|
|
643
|
-
messageQueue.push(data)
|
|
644
|
-
console.log(
|
|
645
|
-
`Queuing message (queue length: ${messageQueue.length}/${maxQueueLength})`,
|
|
646
|
-
)
|
|
647
|
-
// Start queue processor if not already running
|
|
648
|
-
if (!queueProcessor) {
|
|
649
|
-
queueProcessor = setTimeout(processQueue, 100)
|
|
626
|
+
if (messageQueue.length >= maxQueueLength) {
|
|
627
|
+
return {
|
|
628
|
+
err: `Message queue exceeded maximum length (${maxQueueLength}). Update query logic to request less data.`,
|
|
629
|
+
queueLength: messageQueue.length,
|
|
630
|
+
maxQueueLength: maxQueueLength,
|
|
650
631
|
}
|
|
651
|
-
return
|
|
652
632
|
}
|
|
653
633
|
|
|
654
|
-
|
|
655
|
-
|
|
634
|
+
messageQueue.push(data)
|
|
635
|
+
// Start queue processor if not already running
|
|
636
|
+
if (!queueProcessor) {
|
|
637
|
+
queueProcessor = setTimeout(processQueue, 250)
|
|
638
|
+
}
|
|
656
639
|
}
|
|
657
640
|
if (!(opt.peers instanceof Array)) {
|
|
658
641
|
opt.peers = [`ws://localhost:${opt.port || 8765}`]
|
|
@@ -689,7 +672,7 @@ const Wire = opt => {
|
|
|
689
672
|
|
|
690
673
|
// Handle throttle messages from server
|
|
691
674
|
if (msg.throttle && msg.err) {
|
|
692
|
-
console.log(`
|
|
675
|
+
console.log(`Server throttling: ${msg.err}`)
|
|
693
676
|
clientThrottled = true
|
|
694
677
|
throttleUntil = Date.now() + msg.throttle
|
|
695
678
|
return
|