Skip to content

Commit 1725029

Browse files
committed
Refactor rate limiting code for style and clarity
This commit applies consistent formatting, improves code readability, and fixes minor whitespace issues across rate limiting middleware, algorithms, and example/test files. No functional changes were made; the update is purely stylistic to enhance maintainability.
1 parent 19c6ac5 commit 1725029

File tree

8 files changed

+121
-109
lines changed

8 files changed

+121
-109
lines changed

packages/pharaoh_rate_limit/example/basic_rate_limiting.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void main() async {
3333
message: 'Too many authentication attempts, please try again later.',
3434
statusCode: 429,
3535
);
36-
36+
3737
app.use(authLimiter);
3838

3939
app.post('/auth/login', (req, res) {

packages/pharaoh_rate_limit/lib/src/rate_limit_middleware.dart

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,28 @@ import 'sliding_window.dart';
99
class RateLimitOptions {
1010
/// Maximum number of requests allowed
1111
final int max;
12-
12+
1313
/// Time window for rate limiting
1414
final Duration windowMs;
15-
15+
1616
/// Custom message when rate limit is exceeded
1717
final String? message;
18-
18+
1919
/// Custom status code when rate limit is exceeded (default: 429)
2020
final int statusCode;
21-
21+
2222
/// Function to generate a unique key for each client
2323
final String Function(Request req)? keyGenerator;
24-
24+
2525
/// Function to skip rate limiting for certain requests
2626
final bool Function(Request req)? skip;
27-
27+
2828
/// Headers to include in the response
2929
final bool standardHeaders;
30-
30+
3131
/// Legacy headers (X-RateLimit-*)
3232
final bool legacyHeaders;
33-
33+
3434
/// Rate limiting algorithm to use
3535
final RateLimitAlgorithm algorithm;
3636

@@ -54,7 +54,7 @@ enum RateLimitAlgorithm {
5454
}
5555

5656
/// Rate limiting middleware for Pharaoh
57-
///
57+
///
5858
/// Example usage:
5959
/// ```dart
6060
/// app.use(rateLimit(
@@ -85,7 +85,7 @@ Middleware rateLimit({
8585
legacyHeaders: legacyHeaders,
8686
algorithm: algorithm,
8787
);
88-
88+
8989
return RateLimitMiddleware(options).middleware;
9090
}
9191

@@ -94,11 +94,11 @@ Middleware rateLimit({
9494
class RateLimitMiddleware {
9595
final RateLimitOptions options;
9696
late final RateLimiter _limiter;
97-
97+
9898
RateLimitMiddleware(this.options) {
9999
_limiter = _createLimiter();
100100
}
101-
101+
102102
RateLimiter _createLimiter() {
103103
switch (options.algorithm) {
104104
case RateLimitAlgorithm.tokenBucket:
@@ -114,56 +114,59 @@ class RateLimitMiddleware {
114114
);
115115
}
116116
}
117-
117+
118118
Middleware get middleware => (req, res, next) async {
119-
// Skip rate limiting if skip function returns true
120-
if (options.skip?.call(req) == true) {
121-
return next(req);
122-
}
123-
124-
final key = _generateKey(req);
125-
final allowed = _limiter.allowRequest(key);
126-
127-
// Add rate limit headers
128-
_addHeaders(res, key);
129-
130-
if (!allowed) {
131-
final message = options.message ?? 'Too many requests, please try again later.';
132-
return next(res.status(options.statusCode).json({'error': message}));
133-
}
134-
135-
return next(req);
136-
};
137-
119+
// Skip rate limiting if skip function returns true
120+
if (options.skip?.call(req) == true) {
121+
return next(req);
122+
}
123+
124+
final key = _generateKey(req);
125+
final allowed = _limiter.allowRequest(key);
126+
127+
// Add rate limit headers
128+
_addHeaders(res, key);
129+
130+
if (!allowed) {
131+
final message =
132+
options.message ?? 'Too many requests, please try again later.';
133+
return next(res.status(options.statusCode).json({'error': message}));
134+
}
135+
136+
return next(req);
137+
};
138+
138139
String _generateKey(Request req) {
139140
if (options.keyGenerator != null) {
140141
return options.keyGenerator!(req);
141142
}
142-
143+
143144
// Default key generation based on IP address
144145
return req.ipAddr;
145146
}
146-
147+
147148
void _addHeaders(Response res, String key) {
148149
final remaining = _limiter.getRemainingRequests(key);
149150
final resetTime = _limiter.getResetTime(key);
150-
151+
151152
if (options.standardHeaders) {
152153
res.header('RateLimit-Limit', options.max.toString());
153154
res.header('RateLimit-Remaining', remaining.toString());
154155
if (resetTime != null) {
155-
res.header('RateLimit-Reset', (resetTime.millisecondsSinceEpoch ~/ 1000).toString());
156+
res.header('RateLimit-Reset',
157+
(resetTime.millisecondsSinceEpoch ~/ 1000).toString());
156158
}
157159
}
158-
160+
159161
if (options.legacyHeaders) {
160162
res.header('X-RateLimit-Limit', options.max.toString());
161163
res.header('X-RateLimit-Remaining', remaining.toString());
162164
if (resetTime != null) {
163-
res.header('X-RateLimit-Reset', (resetTime.millisecondsSinceEpoch ~/ 1000).toString());
165+
res.header('X-RateLimit-Reset',
166+
(resetTime.millisecondsSinceEpoch ~/ 1000).toString());
164167
}
165168
}
166-
169+
167170
// Add Retry-After header when rate limited
168171
if (remaining <= 0 && resetTime != null) {
169172
final retryAfter = resetTime.difference(DateTime.now()).inSeconds;

packages/pharaoh_rate_limit/lib/src/rate_limiter.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ abstract class RateLimiter {
33
/// Check if a request should be allowed
44
/// Returns true if allowed, false if rate limited
55
bool allowRequest(String key);
6-
6+
77
/// Get remaining requests for the given key
88
int getRemainingRequests(String key);
9-
9+
1010
/// Get reset time for the given key
1111
DateTime? getResetTime(String key);
12-
12+
1313
/// Clean up expired entries
1414
void cleanup();
1515
}

packages/pharaoh_rate_limit/lib/src/sliding_window.dart

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import 'rate_limiter.dart';
22

33
/// Sliding window rate limiter implementation
4-
///
4+
///
55
/// Tracks requests in a sliding time window and enforces limits
66
/// based on the number of requests within that window.
77
class SlidingWindowRateLimiter implements RateLimiter {
88
final int _maxRequests;
99
final Duration _windowSize;
1010
final Map<String, _SlidingWindow> _windows = {};
11-
11+
1212
SlidingWindowRateLimiter({
1313
required int maxRequests,
1414
required Duration windowSize,
15-
}) : _maxRequests = maxRequests,
16-
_windowSize = windowSize;
15+
}) : _maxRequests = maxRequests,
16+
_windowSize = windowSize;
1717

1818
@override
1919
bool allowRequest(String key) {
@@ -37,11 +37,10 @@ class SlidingWindowRateLimiter implements RateLimiter {
3737
void cleanup() {
3838
final now = DateTime.now();
3939
final cutoff = now.subtract(_windowSize.multiply(2));
40-
40+
4141
_windows.removeWhere((key, window) {
4242
window._cleanup();
43-
return window.requests.isEmpty ||
44-
window.requests.first.isBefore(cutoff);
43+
return window.requests.isEmpty || window.requests.first.isBefore(cutoff);
4544
});
4645
}
4746

@@ -50,7 +49,7 @@ class SlidingWindowRateLimiter implements RateLimiter {
5049
if (window == null) {
5150
return _windows[key] = _SlidingWindow(_maxRequests, _windowSize);
5251
}
53-
52+
5453
window._cleanup();
5554
return window;
5655
}
@@ -65,12 +64,12 @@ class _SlidingWindow {
6564

6665
bool allowRequest() {
6766
_cleanup();
68-
67+
6968
if (requests.length < maxRequests) {
7069
requests.add(DateTime.now());
7170
return true;
7271
}
73-
72+
7473
return false;
7574
}
7675

@@ -81,7 +80,7 @@ class _SlidingWindow {
8180
void _cleanup() {
8281
final now = DateTime.now();
8382
final cutoff = now.subtract(windowSize);
84-
83+
8584
requests.removeWhere((timestamp) => timestamp.isBefore(cutoff));
8685
}
8786
}

packages/pharaoh_rate_limit/lib/src/token_bucket.dart

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@ import 'dart:math';
33
import 'rate_limiter.dart';
44

55
/// Token bucket rate limiter implementation
6-
///
6+
///
77
/// Uses the token bucket algorithm where tokens are added to a bucket
88
/// at a fixed rate and requests consume tokens from the bucket.
99
class TokenBucketRateLimiter implements RateLimiter {
1010
final int _capacity;
1111
final int _refillRate;
1212
final Duration _refillInterval;
1313
final Map<String, _TokenBucket> _buckets = {};
14-
14+
1515
TokenBucketRateLimiter({
1616
required int capacity,
1717
required int refillRate,
1818
Duration refillInterval = const Duration(seconds: 1),
19-
}) : _capacity = capacity,
20-
_refillRate = refillRate,
21-
_refillInterval = refillInterval;
19+
}) : _capacity = capacity,
20+
_refillRate = refillRate,
21+
_refillInterval = refillInterval;
2222

2323
@override
2424
bool allowRequest(String key) {
@@ -36,29 +36,31 @@ class TokenBucketRateLimiter implements RateLimiter {
3636
DateTime? getResetTime(String key) {
3737
final bucket = _getBucket(key);
3838
if (bucket.tokens >= _capacity) return null;
39-
39+
4040
final tokensNeeded = _capacity - bucket.tokens;
4141
final timeToRefill = Duration(
42-
milliseconds: (_refillInterval.inMilliseconds * tokensNeeded / _refillRate).round()
43-
);
44-
42+
milliseconds:
43+
(_refillInterval.inMilliseconds * tokensNeeded / _refillRate)
44+
.round());
45+
4546
return bucket.lastRefill.add(timeToRefill);
4647
}
4748

4849
@override
4950
void cleanup() {
5051
final now = DateTime.now();
5152
final cutoff = now.subtract(Duration(hours: 1));
52-
53+
5354
_buckets.removeWhere((key, bucket) => bucket.lastRefill.isBefore(cutoff));
5455
}
5556

5657
_TokenBucket _getBucket(String key) {
5758
final bucket = _buckets[key];
5859
if (bucket == null) {
59-
return _buckets[key] = _TokenBucket(_capacity, _refillRate, _refillInterval);
60+
return _buckets[key] =
61+
_TokenBucket(_capacity, _refillRate, _refillInterval);
6062
}
61-
63+
6264
bucket._refill();
6365
return bucket;
6466
}
@@ -68,7 +70,7 @@ class _TokenBucket {
6870
final int capacity;
6971
final int refillRate;
7072
final Duration refillInterval;
71-
73+
7274
int tokens;
7375
DateTime lastRefill;
7476

@@ -88,11 +90,12 @@ class _TokenBucket {
8890
void _refill() {
8991
final now = DateTime.now();
9092
final timeSinceLastRefill = now.difference(lastRefill);
91-
93+
9294
if (timeSinceLastRefill >= refillInterval) {
93-
final intervalsElapsed = timeSinceLastRefill.inMilliseconds / refillInterval.inMilliseconds;
95+
final intervalsElapsed =
96+
timeSinceLastRefill.inMilliseconds / refillInterval.inMilliseconds;
9497
final tokensToAdd = (intervalsElapsed * refillRate).floor();
95-
98+
9699
tokens = min(capacity, tokens + tokensToAdd);
97100
lastRefill = now;
98101
}

packages/pharaoh_rate_limit/test/sliding_window_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ void main() {
2525
);
2626

2727
expect(limiter.getRemainingRequests('test-key'), equals(2));
28-
28+
2929
limiter.allowRequest('test-key');
3030
expect(limiter.getRemainingRequests('test-key'), equals(1));
31-
31+
3232
limiter.allowRequest('test-key');
3333
expect(limiter.getRemainingRequests('test-key'), equals(0));
3434
});

packages/pharaoh_rate_limit/test/token_bucket_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ void main() {
2727
);
2828

2929
expect(limiter.getRemainingRequests('test-key'), equals(3));
30-
30+
3131
limiter.allowRequest('test-key');
3232
expect(limiter.getRemainingRequests('test-key'), equals(2));
33-
33+
3434
limiter.allowRequest('test-key');
3535
expect(limiter.getRemainingRequests('test-key'), equals(1));
36-
36+
3737
limiter.allowRequest('test-key');
3838
expect(limiter.getRemainingRequests('test-key'), equals(0));
3939
});
@@ -106,7 +106,7 @@ void main() {
106106

107107
// Cleanup should work without errors
108108
limiter.cleanup();
109-
109+
110110
// Verify cleanup method exists and runs
111111
expect(limiter, isA<TokenBucketRateLimiter>());
112112
});

0 commit comments

Comments
 (0)