-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.ts
More file actions
99 lines (86 loc) · 5.68 KB
/
Copy pathserver.ts
File metadata and controls
99 lines (86 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import express from "express";
import path from "path";
import { rateLimits as tokenBucketsLimit } from "./rate-limiters/token-buckets";
import { rateLimits as fixedWindowLimits } from "./rate-limiters/fixed-window";
import { rateLimits as slidingLogLimits } from "./rate-limiters/sliding-log";
import { rateLimits as leakyBucketLimits } from "./rate-limiters/leaky-bucket";
import { rateLimits as slidingCounterLimits } from "./rate-limiters/sliding-counter";
export const app = express();
const PORT = 3456;
app.use(express.static(path.join(__dirname, "public")));
// ── Token Bucket ────────────────────────────────────────────
app.get("/api/token-bucket/hit", tokenBucketsLimit.generalRateLimiter, (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = tokenBucketsLimit.getSnapshotForIp(ip);
const resetsIn = snap.tokens >= snap.capacity ? 0 : Math.ceil((snap.capacity - snap.tokens) / snap.refillRate * 1000);
res.json({ ok: true, algorithm: "token-bucket", ...snap, resetsIn });
});
app.get("/api/token-bucket/status", (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = tokenBucketsLimit.getSnapshotForIp(ip);
const resetsIn = snap.tokens >= snap.capacity ? 0 : Math.ceil((snap.capacity - snap.tokens) / snap.refillRate * 1000);
res.json({ ...snap, resetsIn });
});
// ── Fixed Window ─────────────────────────────────────────────
app.get("/api/fixed-window/hit", fixedWindowLimits.generalRateLimiter, (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = fixedWindowLimits.getSnapshotForIp(ip);
const remaining = snap.maxRequests - snap.requestCount;
const resetsIn = remaining >= snap.maxRequests ? 0 : Math.max(0, snap.windowStart + 10000 - Date.now());
res.json({ ok: true, algorithm: "fixed-window", tokens: remaining, capacity: snap.maxRequests, resetsIn });
});
app.get("/api/fixed-window/status", (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = fixedWindowLimits.getSnapshotForIp(ip);
const remaining = snap.maxRequests - snap.requestCount;
const resetsIn = remaining >= snap.maxRequests ? 0 : Math.max(0, snap.windowStart + 10000 - Date.now());
res.json({ tokens: remaining, capacity: snap.maxRequests, resetsIn });
});
// ── Sliding Window Log ──────────────────────────────────────
app.get("/api/sliding-window-log/hit", slidingLogLimits.generalRateLimiter, (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = slidingLogLimits.getSnapshotForIp(ip);
const remaining = snap.maxRequests - snap.requestCount;
const resetsIn = remaining >= snap.maxRequests ? 0 : (snap.oldestTs ? Math.max(0, snap.oldestTs + 10000 - Date.now()) : 0);
res.json({ ok: true, algorithm: "sliding-window-log", tokens: remaining, capacity: snap.maxRequests, resetsIn });
});
app.get("/api/sliding-window-log/status", (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = slidingLogLimits.getSnapshotForIp(ip);
const remaining = snap.maxRequests - snap.requestCount;
const resetsIn = remaining >= snap.maxRequests ? 0 : (snap.oldestTs ? Math.max(0, snap.oldestTs + 10000 - Date.now()) : 0);
res.json({ tokens: remaining, capacity: snap.maxRequests, resetsIn });
});
// ── Sliding Window Counter ───────────────────────────────────
app.get("/api/sliding-window-counter/hit", slidingCounterLimits.generalRateLimiter, (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = slidingCounterLimits.getSnapshotForIp(ip);
const remaining = snap.maxRequests - snap.requestCount;
const resetsIn = remaining >= snap.maxRequests ? 0 : Math.max(0, snap.windowStart + 10000 - Date.now());
res.json({ ok: true, algorithm: "sliding-window-counter", tokens: remaining, capacity: snap.maxRequests, resetsIn, prevCount: snap.prevCount, currCount: snap.currCount, weight: snap.weight });
});
app.get("/api/sliding-window-counter/status", (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = slidingCounterLimits.getSnapshotForIp(ip);
const remaining = snap.maxRequests - snap.requestCount;
const resetsIn = remaining >= snap.maxRequests ? 0 : Math.max(0, snap.windowStart + 10000 - Date.now());
res.json({ tokens: remaining, capacity: snap.maxRequests, resetsIn, prevCount: snap.prevCount, currCount: snap.currCount, weight: snap.weight });
});
// ── Leaky Bucket ─────────────────────────────────────────────
app.get("/api/leaky-bucket/hit", leakyBucketLimits.generalRateLimiter, (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = leakyBucketLimits.getSnapshotForIp(ip);
const remaining = snap.capacity - snap.tokens;
res.json({ ok: true, algorithm: "leaky-bucket", tokens: remaining, capacity: snap.capacity, resetsIn: snap.resetsIn });
});
app.get("/api/leaky-bucket/status", (req, res) => {
const ip = req.ip || req.socket.remoteAddress || "unknown";
const snap = leakyBucketLimits.getSnapshotForIp(ip);
const remaining = snap.capacity - snap.tokens;
res.json({ tokens: remaining, capacity: snap.capacity, resetsIn: snap.resetsIn });
});
if (process.env.VERCEL !== "1") {
app.listen(PORT, () => {
console.log(`Rate Limiting Dashboard → http://localhost:${PORT}`);
});
}