forked from evanp/onepage.pub
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rate-limit.mjs
130 lines (113 loc) · 3.35 KB
/
rate-limit.mjs
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import { describe, beforeEach, afterEach, it } from 'node:test'
import assert from 'node:assert'
import https from 'node:https'
import { readFileSync } from 'node:fs'
const MAIN_PORT = process.env.OPP_PORT
console.log(`\nRate Limit: ${process.env.OPP_RATE_LIMIT}\n\nstarting rate limit tests\n`)
/**
* Integration tests for rate limiting middleware.
*
* Sets up an HTTPS server and makes requests to test:
* - Requests per IP are limited
* - Requests below limit are allowed
* - Standard rate limit headers are used
*/
describe("request rate limits", () => {
const options = {
hostname: "localhost",
port: MAIN_PORT,
path: "/",
method: "GET",
};
beforeEach(() => {
const options = {
key: readFileSync(process.env.OPP_KEY),
cert: readFileSync(process.env.OPP_CERT),
};
try {
https
.createServer(options, (req, res) => {
try {
res.writeHead(200);
res.end("hello world\n hello");
} catch (err) {
console.error(err);
res.statusCode = 500;
res.end("Internal Server Error");
}
})
.listen(process.env.OPP_PORT);
} catch (err) {
console.error("Error starting HTTPS server:", err);
process.exit(1);
}
});
afterEach(() => {
https.close;
});
it("should limit requests per IP", async () => {
let nextCallCount = 0;
// Call limiter middleware multiple times from same IP
for (let i = 0; i < +process.env.OPP_RATE_LIMIT + 50; i++) {
const req = https.request(options, (res) => {
if (res.statusCode === 200) {
// success
nextCallCount++;
} else {
// handle error
}
});
req.on("error", (e) => {
if (e.message != "self-signed certificate") {
console.error(`problem with request: ${e.message}`);
}
});
req.end();
}
return nextCallCount;
// Assert request was blocked after exceeding limit
assert.strictEqual(nextCallCount, 100);
});
it("should allow requests below limit", async () => {
let nextCallCount = 0;
// Call limiter middleware below limit
for (let i = 0; i < +process.env.OPP_RATE_LIMIT - 50; i++) {
const req = https.request(options, (res) => {
if (res.statusCode === 200) {
// success
nextCallCount++;
} else {
// handle error
}
});
req.on("error", (e) => {
if (e.message != "self-signed certificate") {
console.error(`problem with request: ${e.message}`);
}
});
req.end();
}
return nextCallCount;
// Assert all 50 requests were processed
assert.strictEqual(nextCallCount, 50);
});
it("uses standard headers", async () => {
const req = https.request(options, (res) => {
if (res.statusCode === 200) {
// success
assert(res.headers["RateLimit-Limit"]);
assert(res.headers["RateLimit-Remaining"]);
assert(res.headers["RateLimit-Reset"]);
assert(!res.headers["X-RateLimit-Limit"]);
assert(!res.headers["X-RateLimit-Remaining"]);
assert(!res.headers["X-RateLimit-Reset"]);
}
});
req.on("error", (e) => {
if (e.message != "self-signed certificate") {
console.error(`problem with request: ${e.message}`);
}
});
req.end();
});
});