Proteção de APIs com Rate Limiting Manual em Node.js HTTP
Servidores sem controle de tráfego estão vulneráveis a ataques de força bruta, negação de serviço (DoS) e consumo excessivo de recursos. A implementação de um middleware de Rate Limiting simples em Node.js resolve esse problema interceptando as requisições por IP e bloqueando conexões que excedam o limite estabelecido dentro de uma janela de tempo.
JavaScript
const http = require('http');
// Armazena a contagem de requisições por IP em memória
const taxaLimites = new Map();
/**
* Middleware para controlar a taxa de requisições por IP
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {number} limiteMaximo - Máximo de requisições permitidas
* @param {number} janelaMs - Intervalo de tempo em milissegundos
* @returns {boolean} Retorna true se a requisição for permitida
*/
function rateLimiter(req, res, limiteMaximo = 5, janelaMs = 60000) {
const ip = req.socket.remoteAddress || '127.0.0.1';
const agora = Date.now();
if (!taxaLimites.has(ip)) {
taxaLimites.set(ip, { contagem: 1, inicioJanela: agora });
return true;
}
const registro = taxaLimites.get(ip);
// Reseta a contagem caso a janela de tempo tenha expirado
if (agora - registro.inicioJanela > janelaMs) {
registro.contagem = 1;
registro.inicioJanela = agora;
return true;
}
// Incrementa o contador de requisições
registro.contagem += 1;
// Bloqueia a requisição se exceder o limite
if (registro.contagem > limiteMaximo) {
res.writeHead(429, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ erro: 'Muitas requisições. Tente novamente mais tarde.' }));
return false;
}
return true;
}
// --- Exemplo Prático de Uso ---
const servidor = http.createServer((req, res) => {
// Executa o rate limiter (limite de 3 requisições por minuto para teste)
if (!rateLimiter(req, res, 3, 60000)) return;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ mensagem: 'Requisição processada com sucesso!' }));
});
servidor.listen(3000, () => {
console.log('Servidor rodando em http://localhost:3000');
});
Pontos-chave
- Status HTTP 429 Too Many Requests: É o código de status padrão da RFC 6585 para sinalizar ao cliente que o limite de requisições foi atingido.
- Captura do Endereço IP: Utiliza
req.socket.remoteAddress; em ambientes com proxies reversos (ex: Nginx, Cloudflare), deve-se ler o cabeçalhox-forwarded-for. - Gerenciamento de Memória em Produção: O uso de
Mapem memória é ideal para testes e serviços simples, mas para aplicações distribuídas ou com tráfego alto recomenda-se utilizar um banco em memória como Redis. - Limpeza Automática de Chaves: Para evitar memory leaks com conexões de muitos IPs diferentes, implemente uma rotina de expiração via
setIntervalpara apagar registros antigos doMap.
