feat: Implement caching and rate limiting for API requests
This commit is contained in:
52
test/limits.test.js
Normal file
52
test/limits.test.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { rateLimit, semaphore } from "../server/limits.js";
|
||||
|
||||
test("Импорт: не больше двух разборов сразу, лишние ждут или получают 429", async () => {
|
||||
const run = semaphore({ limit: 2, queue: 1, message: "Занято" });
|
||||
let active = 0,
|
||||
peak = 0;
|
||||
const release = [];
|
||||
const task = () =>
|
||||
run(async () => {
|
||||
peak = Math.max(peak, ++active);
|
||||
await new Promise((resolve) => release.push(resolve));
|
||||
active--;
|
||||
});
|
||||
const running = [task(), task(), task()];
|
||||
await assert.rejects(task(), (e) => e.status === 429 && e.message === "Занято");
|
||||
// Each finished task hands its slot to the one waiting.
|
||||
while (release.length) {
|
||||
release.shift()();
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
}
|
||||
await Promise.all(running);
|
||||
assert.equal(peak, 2);
|
||||
// All slots are free again.
|
||||
assert.equal(await run(async () => "ok"), "ok");
|
||||
});
|
||||
|
||||
test("Импорт: лимит запросов считается по адресу клиента", () => {
|
||||
const limit = rateLimit({ max: 2, windowMs: 60_000, message: "Подождите" });
|
||||
const call = (ip) => {
|
||||
let status = 200,
|
||||
body = null,
|
||||
passed = false;
|
||||
const res = {
|
||||
set() {},
|
||||
status(code) {
|
||||
status = code;
|
||||
return this;
|
||||
},
|
||||
json(value) {
|
||||
body = value;
|
||||
},
|
||||
};
|
||||
limit({ ip }, res, () => (passed = true));
|
||||
return { status, body, passed };
|
||||
};
|
||||
assert.ok(call("10.0.0.1").passed);
|
||||
assert.ok(call("10.0.0.1").passed);
|
||||
assert.deepEqual(call("10.0.0.1"), { status: 429, body: { error: "Подождите" }, passed: false });
|
||||
assert.ok(call("10.0.0.2").passed);
|
||||
});
|
||||
Reference in New Issue
Block a user