reflo 1.0.2 → 1.0.4
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/.github/workflows/release.yml +1 -1
- package/CHANGELOG.md +14 -0
- package/README.md +134 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## [1.0.4](https://github.com/theanuragshukla/reflo/compare/v1.0.3...v1.0.4) (2025-07-06)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* update README ([056b094](https://github.com/theanuragshukla/reflo/commit/056b094f35326b3bf9b906357948f4c7ede3f6df))
|
7
|
+
|
8
|
+
## [1.0.3](https://github.com/theanuragshukla/reflo/compare/v1.0.2...v1.0.3) (2025-07-06)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* update gh token in workflow ([ead48c6](https://github.com/theanuragshukla/reflo/commit/ead48c650b673c6e3bb70cd78ccc36f091fb7a56))
|
14
|
+
|
1
15
|
## [1.0.2](https://github.com/theanuragshukla/reflo/compare/v1.0.1...v1.0.2) (2025-07-06)
|
2
16
|
|
3
17
|
|
package/README.md
CHANGED
@@ -1,2 +1,136 @@
|
|
1
1
|
# Reflo
|
2
2
|
|
3
|
+
Redis-backed rate limiter middleware for Express applications using token bucket algorithm.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
npm install reflo
|
9
|
+
```
|
10
|
+
|
11
|
+
## Quick Start
|
12
|
+
|
13
|
+
```typescript
|
14
|
+
import express from 'express';
|
15
|
+
import { rateLimiter } from 'reflo';
|
16
|
+
|
17
|
+
const app = express();
|
18
|
+
|
19
|
+
app.use(rateLimiter({
|
20
|
+
timeWindowSeconds: 60,
|
21
|
+
requestCount: 100,
|
22
|
+
}));
|
23
|
+
|
24
|
+
app.listen(3000);
|
25
|
+
```
|
26
|
+
|
27
|
+
## Configuration
|
28
|
+
|
29
|
+
```typescript
|
30
|
+
interface LimiterConfig {
|
31
|
+
timeWindowSeconds: number;
|
32
|
+
requestCount: number;
|
33
|
+
exceptions?: Array<{ route: string; count: number }>;
|
34
|
+
allowlist?: string[];
|
35
|
+
blocklist?: string[];
|
36
|
+
getIdentifier?: (req: Request) => string;
|
37
|
+
backoffStrategy?: (overuse: number) => number;
|
38
|
+
}
|
39
|
+
```
|
40
|
+
|
41
|
+
| Option | Type | Description |
|
42
|
+
|--------|------|-------------|
|
43
|
+
| `timeWindowSeconds` | `number` | Rate limit window in seconds |
|
44
|
+
| `requestCount` | `number` | Maximum requests per window |
|
45
|
+
| `exceptions` | `Array<{route, count}>` | Per-route limit overrides |
|
46
|
+
| `allowlist` | `string[]` | Bypass rate limiting |
|
47
|
+
| `blocklist` | `string[]` | Always blocked |
|
48
|
+
| `getIdentifier` | `(req) => string` | User identification function |
|
49
|
+
| `backoffStrategy` | `(overuse) => number` | Delay calculation function |
|
50
|
+
|
51
|
+
## Strategies
|
52
|
+
|
53
|
+
### Identifier Strategies
|
54
|
+
|
55
|
+
```typescript
|
56
|
+
import { identifierStrategies } from 'reflo';
|
57
|
+
|
58
|
+
// By IP address
|
59
|
+
identifierStrategies.byIP()
|
60
|
+
|
61
|
+
// By header value
|
62
|
+
identifierStrategies.byHeader('x-api-key')
|
63
|
+
```
|
64
|
+
|
65
|
+
### Backoff Strategies
|
66
|
+
|
67
|
+
```typescript
|
68
|
+
import { backoffStrategies } from 'reflo';
|
69
|
+
|
70
|
+
backoffStrategies.none() // No delay
|
71
|
+
backoffStrategies.fixed(500) // Fixed 500ms delay
|
72
|
+
backoffStrategies.linear(100, 5000) // Linear: 100ms * overuse, max 5s
|
73
|
+
backoffStrategies.exponential(200, 10000) // Exponential: 200ms * 2^overuse, max 10s
|
74
|
+
```
|
75
|
+
|
76
|
+
## Advanced Usage
|
77
|
+
|
78
|
+
### Per-Route Limits
|
79
|
+
|
80
|
+
```typescript
|
81
|
+
app.use(rateLimiter({
|
82
|
+
timeWindowSeconds: 60,
|
83
|
+
requestCount: 100,
|
84
|
+
exceptions: [
|
85
|
+
{ route: '/api/upload', count: 5 },
|
86
|
+
{ route: '/api/search', count: 500 },
|
87
|
+
],
|
88
|
+
}));
|
89
|
+
```
|
90
|
+
|
91
|
+
### Allow/Block Lists
|
92
|
+
|
93
|
+
```typescript
|
94
|
+
app.use(rateLimiter({
|
95
|
+
timeWindowSeconds: 60,
|
96
|
+
requestCount: 100,
|
97
|
+
allowlist: ['ip:127.0.0.1', 'hdr:x-api-key:admin-key'],
|
98
|
+
blocklist: ['ip:192.168.1.100'],
|
99
|
+
}));
|
100
|
+
```
|
101
|
+
|
102
|
+
### Custom Strategies
|
103
|
+
|
104
|
+
```typescript
|
105
|
+
const customIdentifier = (req) => `user:${req.user?.id || req.ip}`;
|
106
|
+
const customBackoff = (overuse) => Math.min(1000, 50 * Math.pow(overuse, 1.5));
|
107
|
+
|
108
|
+
app.use(rateLimiter({
|
109
|
+
timeWindowSeconds: 60,
|
110
|
+
requestCount: 100,
|
111
|
+
getIdentifier: customIdentifier,
|
112
|
+
backoffStrategy: customBackoff,
|
113
|
+
}));
|
114
|
+
```
|
115
|
+
|
116
|
+
## Environment Variables
|
117
|
+
|
118
|
+
```bash
|
119
|
+
REDIS_URL=redis://localhost:6379
|
120
|
+
REDIS_TLS=true # Enable TLS connection
|
121
|
+
```
|
122
|
+
|
123
|
+
## Response Headers
|
124
|
+
|
125
|
+
- `X-RateLimit-Limit`: Maximum requests allowed
|
126
|
+
- `X-RateLimit-Remaining`: Requests remaining in current window
|
127
|
+
|
128
|
+
## Requirements
|
129
|
+
|
130
|
+
- Node.js 14+
|
131
|
+
- Redis server
|
132
|
+
- Express application
|
133
|
+
|
134
|
+
## License
|
135
|
+
|
136
|
+
MIT
|
package/package.json
CHANGED