@@ -45,16 +45,8 @@ interface RateLimitResult {
4545 reset : number ;
4646}
4747
48- const trackers = new Map < string , { count : number ; expires : number } > ( ) ;
48+ const trackers = new TTLCache < { count : number } > ( 2000 , 60000 ) ;
4949
50- /**
51- * Checks if a request from a given IP should be rate limited.
52- *
53- * @param ip The IP address to track
54- * @param limit Maximum number of requests allowed in the window
55- * @param windowMs Time window in milliseconds
56- * @returns RateLimitResult
57- */
5850export function rateLimit (
5951 ip : string ,
6052 limit : number = 60 ,
@@ -63,46 +55,32 @@ export function rateLimit(
6355 const now = Date . now ( ) ;
6456 const tracker = trackers . get ( ip ) ;
6557
66- // Periodic cleanup of the map to prevent memory leaks.
67- // We perform a partial cleanup if the map grows too large.
68- if ( trackers . size > 2000 ) {
69- let cleaned = 0 ;
70- for ( const [ key , value ] of trackers . entries ( ) ) {
71- if ( now > value . expires ) {
72- trackers . delete ( key ) ;
73- cleaned ++ ;
74- }
75- // Stop cleaning after some work to avoid blocking the request for too long
76- if ( cleaned > 500 ) break ;
77- }
78- }
79-
80- if ( ! tracker || now > tracker . expires ) {
81- const expires = now + windowMs ;
82- trackers . set ( ip , { count : 1 , expires } ) ;
58+ if ( ! tracker ) {
59+ trackers . set ( ip , { count : 1 } , windowMs ) ;
8360 return {
8461 success : true ,
8562 limit,
8663 remaining : limit - 1 ,
87- reset : expires ,
64+ reset : now + windowMs ,
8865 } ;
8966 }
9067
9168 tracker . count ++ ;
69+ trackers . set ( ip , tracker , windowMs ) ;
9270
9371 if ( tracker . count > limit ) {
9472 return {
9573 success : false ,
9674 limit,
9775 remaining : 0 ,
98- reset : tracker . expires ,
76+ reset : now + windowMs ,
9977 } ;
10078 }
10179
10280 return {
10381 success : true ,
10482 limit,
10583 remaining : limit - tracker . count ,
106- reset : tracker . expires ,
84+ reset : now + windowMs ,
10785 } ;
10886}
0 commit comments