redis-traffic-limiter 1.0.0

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/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # Redis Rate Limiter
2
+
3
+ A lightweight Redis-based rate limiter for Node.js using Redis.
4
+
5
+ Currently supported algorithms:
6
+
7
+ - ✅ Fixed Window
8
+ - ✅ Sliding Window
9
+
10
+ ---
11
+
12
+ ## Prerequisites
13
+
14
+ Before using this package, make sure you have:
15
+
16
+ - Node.js
17
+ - Redis Server
18
+
19
+ ---
20
+
21
+ ## Install Redis
22
+
23
+ ### Ubuntu
24
+
25
+ ```bash
26
+ sudo apt update
27
+ sudo apt install redis-server
28
+ ```
29
+
30
+ Start Redis
31
+
32
+ ```bash
33
+ redis-server
34
+ ```
35
+
36
+ ### Windows
37
+
38
+ Run Redis using Docker:
39
+
40
+ ```bash
41
+ docker run -d \
42
+ --name redis \
43
+ -p 6379:6379 \
44
+ redis
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Installation
50
+
51
+ Install the package along with the official Redis client.
52
+
53
+ ```bash
54
+ npm install redis-traffic-limiter redis
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Create a Redis Client
60
+
61
+ ```js
62
+ import { createClient } from "redis";
63
+
64
+ const redis = createClient({
65
+ url: "redis://localhost:6379"
66
+ });
67
+
68
+ await redis.connect();
69
+ ```
70
+
71
+ Pass the connected Redis client while creating the limiter.
72
+
73
+ ---
74
+
75
+ ## Usage
76
+
77
+ Example programs are available in the `examples/` directory.
78
+
79
+ - `examples/fixed.js`
80
+ - `examples/sliding.js`
81
+
82
+ Run them using:
83
+
84
+ ```bash
85
+ node examples/fixed.js
86
+ ```
87
+
88
+ or
89
+
90
+ ```bash
91
+ node examples/sliding.js
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Supported Algorithms
97
+
98
+ - Fixed Window
99
+ - Sliding Window
100
+
101
+ ---
102
+
103
+ ## Notes
104
+
105
+ - The package expects a **connected node-redis client**.
106
+ - Redis connections are managed by your application.
107
+ - `window` is specified in **milliseconds**.
108
+ - Currently supports the official **node-redis** client only.
109
+ - Support for additional Redis clients (e.g. ioredis) is planned for future releases.
110
+
111
+ ---
112
+
113
+ ## License
114
+
115
+ MIT
@@ -0,0 +1,27 @@
1
+ import { createClient } from "redis";
2
+ import { FixedWindow } from "../src/index.js";
3
+
4
+ // Create a Redis client.
5
+ // By default Redis runs on localhost:6379.
6
+ const redis = createClient({
7
+ url: "redis://localhost:6379"
8
+ });
9
+
10
+ // Connect to Redis before using it.
11
+ await redis.connect();
12
+
13
+ // Create a Fixed Window limiter.
14
+ // window is in milliseconds.
15
+ const limiter = new FixedWindow({
16
+ redis,
17
+ window: 60000,
18
+ max: 5
19
+ });
20
+
21
+ // Consume one request for this user.
22
+ const result = await limiter.consume("user:1");
23
+
24
+ console.log(result);
25
+
26
+ // Close the Redis connection.
27
+ await redis.quit();
@@ -0,0 +1,25 @@
1
+ import { createClient } from "redis";
2
+ import { SlidingWindow } from "../src/index.js";
3
+
4
+ // Create a Redis client.
5
+ const redis = createClient({
6
+ url: "redis://localhost:6379"
7
+ });
8
+
9
+ // Connect to Redis.
10
+ await redis.connect();
11
+
12
+ // Create a Sliding Window limiter.
13
+ const limiter = new SlidingWindow({
14
+ redis,
15
+ window: 60000,
16
+ max: 5
17
+ });
18
+
19
+ // Consume one request.
20
+ const result = await limiter.consume("user:1");
21
+
22
+ console.log(result);
23
+
24
+ // Close Redis connection.
25
+ await redis.quit();
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "redis-traffic-limiter",
3
+ "version": "1.0.0",
4
+ "description": "A lightweight Redis-based rate limiter for Node.js supporting Fixed Window and Sliding Window algorithms.",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js"
9
+ },
10
+ "keywords": [
11
+ "redis",
12
+ "rate-limiter",
13
+ "traffic",
14
+ "limiter",
15
+ "nodejs",
16
+ "backend",
17
+ "fixed-window",
18
+ "sliding-window"
19
+ ],
20
+ "author": "Bhuvan",
21
+ "license": "MIT",
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "dependencies": {
26
+ "redis": "^6.1.0"
27
+ }
28
+ }
package/src/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default as FixedWindow } from "./limiter/FixedWindow.js";
2
+ export { default as SlidingWindow } from "./limiter/SlidingWindow.js";
@@ -0,0 +1,32 @@
1
+ class FixedWindow {
2
+
3
+ constructor({ redis, window, max }) {
4
+ this.redis = redis;
5
+ this.window = window;
6
+ this.max = max;
7
+ }
8
+
9
+ async consume(key) {
10
+
11
+ const count = await this.redis.incr(key);
12
+
13
+ if (count === 1) {
14
+ await this.redis.expire(key, this.window);
15
+ }
16
+
17
+ if (count <= this.max) {
18
+ return {
19
+ allowed: true,
20
+ remaining: this.max - count
21
+ };
22
+ }
23
+
24
+ return {
25
+ allowed: false,
26
+ remaining: 0
27
+ };
28
+ }
29
+
30
+ }
31
+
32
+ export default FixedWindow;
@@ -0,0 +1,54 @@
1
+ class SlidingWindow {
2
+
3
+ constructor({ redis, window, max }) {
4
+ this.redis = redis;
5
+ this.window = window;
6
+ this.max = max;
7
+ }
8
+
9
+ async consume(key) {
10
+
11
+ const now = Date.now();
12
+
13
+
14
+ await this.redis.zRemRangeByScore(
15
+ key,
16
+ 0,
17
+ now - this.window
18
+ );
19
+
20
+
21
+ const count = await this.redis.zCard(key);
22
+
23
+
24
+ if (count >= this.max) {
25
+
26
+ return {
27
+ allowed: false,
28
+ remaining: 0
29
+ };
30
+
31
+ }
32
+
33
+
34
+ await this.redis.zAdd(key, {
35
+ score: now,
36
+ value: `${now}-${Math.random()}`
37
+ });
38
+
39
+
40
+ await this.redis.expire(
41
+ key,
42
+ Math.ceil(this.window / 1000)
43
+ );
44
+
45
+ return {
46
+ allowed: true,
47
+ remaining: this.max - count - 1
48
+ };
49
+
50
+ }
51
+
52
+ }
53
+
54
+ export default SlidingWindow;