Rate Limiting в JavaScript (Node.js): Полное руководство по библиотеке express-rate-limit

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Rate Limiting в JavaScript (Node.js): Защита API с помощью express-rate-limit

В современном веб-разработке защита серверных приложений от чрезмерной нагрузки и злонамеренных атак является критически важной задачей. Одним из наиболее эффективных механизмов защиты является rate limiting (ограничение частоты запросов). Этот подход позволяет контролировать количество запросов, которые клиент (IP-адрес, пользователь или сессия) может отправить на сервер за определенный промежуток времени. В экосистеме Node.js и Express наиболее популярной и надежной библиотекой для реализации rate limiting является express-rate-limit.

Что такое rate limiting и зачем он нужен?

Rate limiting — это техника, используемая для управления трафиком в сети. Она предотвращает злоупотребление ресурсами сервера, защищая от:

  • DoS/DDoS-атак — массовых запросов с целью вывести сервер из строя.
  • Brute-force атак — перебора паролей или токенов доступа.
  • Web scraping — автоматического сбора данных с сайта.
  • Чрезмерного использования API — когда один клиент потребляет больше ресурсов, чем положено.

Без rate limiting ваше приложение может стать уязвимым и нестабильным, особенно при росте пользовательской базы.

Библиотека express-rate-limit

express-rate-limit — это middleware для Express.js, который предоставляет простой и гибкий способ ограничения запросов. Она встраивается в цепочку обработки запросов и автоматически отслеживает количество обращений от каждого клиента. Библиотека поддерживает различные хранилища (в памяти, Redis, MongoDB и другие), что делает ее масштабируемой для распределенных систем.

Установка

Для начала работы установите библиотеку через npm:

npm install express-rate-limit

Базовое использование

Самый простой пример — ограничение всех маршрутов приложения до 100 запросов в час с одного IP-адреса:

const rateLimit = require('express-rate-limit');
const express = require('express');
const app = express();

// Создаем лимитер
const limiter = rateLimit({
    windowMs: 60 * 60 * 1000, // 1 час
    max: 100, // максимум 100 запросов
    message: 'Слишком много запросов с вашего IP. Пожалуйста, попробуйте позже.',
    standardHeaders: true, // Возвращает стандартные заголовки RateLimit-*
    legacyHeaders: false, // Отключает заголовки X-RateLimit-*
});

// Применяем ко всем маршрутам
app.use(limiter);

app.get('/', (req, res) => {
    res.send('Главная страница');
});

app.listen(3000, () => {
    console.log('Сервер запущен на порту 3000');
});

Настройка для разных маршрутов

Часто требуется разное ограничение для различных эндпоинтов. Например, для маршрута входа в систему можно установить более строгий лимит:

const rateLimit = require('express-rate-limit');

// Строгий лимит для /api/login
const loginLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 минут
    max: 5, // 5 попыток входа
    message: {
        error: 'Слишком много попыток входа. Попробуйте через 15 минут.',
        retryAfter: 15
    },
    keyGenerator: (req) => {
        // Используем IP + имя пользователя для более точной блокировки
        return req.ip + req.body.username;
    }
});

app.post('/api/login', loginLimiter, (req, res) => {
    // Логика аутентификации
    res.send('Вход выполнен');
});

// Мягкий лимит для публичного API
const apiLimiter = rateLimit({
    windowMs: 60 * 1000, // 1 минута
    max: 30, // 30 запросов в минуту
    message: 'Превышен лимит запросов к API.'
});

app.use('/api/', apiLimiter);

Расширенные возможности

Кастомные хранилища

По умолчанию данные хранятся в памяти процесса. Для продакшена рекомендуется использовать Redis или MongoDB. Пример с Redis через rate-limit-redis:

const RedisStore = require('rate-limit-redis');
const Redis = require('ioredis');
const redisClient = new Redis();

const limiter = rateLimit({
    store: new RedisStore({
        sendCommand: (...args) => redisClient.call(...args),
    }),
    windowMs: 60 * 60 * 1000,
    max: 100,
});

Пропуск определенных запросов

Иногда нужно исключить из лимитирования некоторые запросы (например, от доверенных IP):

const limiter = rateLimit({
    windowMs: 60 * 60 * 1000,                    

Рекомендаций