#javascript #node.js #jestjs #supertest
Вопрос:
У меня в телефоне есть ограничитель скорости (без экспресса и т. Д.). node.js приложение, которое отклоняет запросы, если они превышают лимит в течение некоторого временного окна. Он фильтрует как все запросы к серверу, так и уникальные запросы (на основе информации о заголовке ip-адреса и устройства в запросе). Мне нужно полностью покрыть его тестами, но я не знаю, как это сделать.
- Мой текущий тест не работает, потому что массив обещанных запросов по какой-то причине пуст.
- Даже если это сработает, я не знаю, как протестировать его на основе всех запросов (мне нужно, чтобы ip-адрес или заголовок устройства отличались при каждом запросе).
Я был бы очень признателен за любую помощь! Спасибо!
rateLimiter.test.js:
const http = require('http'); const request = require('supertest'); const { requestHandler } = require('../src/modules/requestHandler'); const { uniqueRequests } = require('../src/config/config').rateLimiter; const server = http .createServer(async (req, res) =gt; { requestHandler(req, res); }) .listen(8001); test('Login test', async () =gt; { const results = []; for (let i; i lt; uniqueRequests 5; i 1) { results.push( request(server).post('/api/login').send({ email: 'email@email.com', password: '555555', }) ); } await Promise.all(results); console.log(results); // outputs '[]' expect(results.find(el =gt; el.statusCode === 500)).not.toEqual(undefined); });
rateLimiter.js:
const { plainTextResponse } = require('./utils'); const users = new Map(); let frameStart = Date.now(); let requestsCounter = 0; const parseIp = req =gt; (typeof req.headers['x-forwarded-for'] === 'string' amp;amp; req.headers['x-forwarded-for'].split(',').shift()) || req.connection?.remoteAddress || req.socket?.remoteAddress || req.connection?.socket?.remoteAddress; async function rateLimiter(req, res, next, window, requests, uniqueRequests) { const ip = parseIp(req); const user = req.headers['user-agent']; const device = ip.concat(':', user); const deviceRequests = users.get(device); if (requestsCounter gt; requests || deviceRequests gt; uniqueRequests) { plainTextResponse(res, 500, 'Too much requests!'); } else { next(req, res); } if (Date.now() - frameStart gt; window) { users.clear(); frameStart = Date.now(); requestsCounter = 0; } requestsCounter = 1; users.set(device, !deviceRequests ? 1 : deviceRequests 1); } module.exports = { rateLimiter };
requestHandler.js:
const { window, requests, uniqueRequests, } = require('../config/config.js').rateLimiter; const { rateLimiter } = require('./rateLimiter'); async function requestHandler(req, res) { if (req.method === 'GET') { getHandler(req, res); } else if (req.method === 'POST') { rateLimiter(req, res, postHandler, window, requests, uniqueRequests); } } module.exports = { requestHandler };
config.js:
module.exports = { rateLimiter: { window: 10000, requests: 1000, uniqueRequests: 20, }, };