Ограничитель (Limiter)

Это промежуточное ПО для Fiber, которое используется для ограничения повторяющихся запросов к публичным API и/или конечным точкам (например, сброс пароля). Также полезно ограничивать частоту обращений клиентов к API, веб-сканеров или других задач, требующих ограничение частоты.

Примечание: Это промежуточное ПО использует наш пакет Storage для поддержки различных баз данных через унифицированный интерфейс. Конфигурация по умолчанию хранит данные в памяти, и вы можете обратиться к приведенному ниже примеру для просмотра других баз данных.

Примечание: По умолчанию этот модуль не делится состоянием с другими процессами/серверами.

Сигнатура

func New(config ...Config) fiber.Handler

Пример

Импортируйте пакет промежуточного ПО как часть веб-фреймворка Fiber:

import (
  "github.com/gofiber/fiber/v2"
  "github.com/gofiber/fiber/v2/middleware/limiter"
)

После создания приложения Fiber, вы можете использовать следующие параметры:

// Инициализация с конфигурацией по умолчанию
app.Use(limiter.New())

// Или расширение с пользовательской конфигурацией
app.Use(limiter.New(limiter.Config{
    Next: func(c *fiber.Ctx) bool {
        return c.IP() == "127.0.0.1"
    },
    Max:          20,
    Expiration:     30 * time.Second,
    KeyGenerator:          func(c *fiber.Ctx) string {
        return c.Get("x-forwarded-for")
    },
    LimitReached: func(c *fiber.Ctx) error {
        return c.SendFile("./toofast.html")
    },
    Storage: myCustomStorage{},
}))

Скользящее окно

Вы можете включить алгоритм скользящего окна вместо использования стандартного фиксированного алгоритма окна.

Пример конфигурации:

app.Use(limiter.New(limiter.Config{
    Max:            20,
    Expiration:     30 * time.Second,
    LimiterMiddleware: limiter.SlidingWindow{},
}))

Это означает, что каждое окно будет учитывать предыдущее окно (если оно есть). Формула для данной частоты следующая:

весПредыдущегоОкна = количество запросов в предыдущем окне * (когдаНовоеОкно / Expiration)
частота = весПредыдущегоОкна + количество запросов в текущем окне.

Конфигурация

Свойство Тип Описание По умолчанию
Next func(*fiber.Ctx) bool Next определяет функцию для пропуска этого промежуточного ПО при возвращении true. nil
Max int Максимальное количество соединений в течение Expiration секунд, возвращая ответ 429 в случае превышения. 5
KeyGenerator func(*fiber.Ctx) string KeyGenerator позволяет генерировать пользовательские ключи, используя c.IP() по умолчанию. Функция, использующая c.IP() в качестве значения по умолчанию
Expiration time.Duration Expiration - время хранения записей запросов в памяти. 1 * time.Minute
LimitReached fiber.Handler Вызывается, когда достигнут лимит. Функция отправляющая ответ 429
SkipFailedRequests bool Если true, не считать запросы с StatusCode >= 400. false
SkipSuccessfulRequests bool Если true, не считать запросы с StatusCode < 400. false
Storage fiber.Storage Хранилище, используемое для хранения состояния промежуточного ПО. Хранилище в памяти только для текущего процесса
LimiterMiddleware LimiterHandler LimiterMiddleware - структура, реализующая промежуточное ПО ограничителя. Новый ограничитель частоты с фиксированным окном
Duration (Устаревшее) time.Duration Устаревшее: используйте вместо этого Expiration. -
Store (Устаревшее) fiber.Storage Устаревшее: используйте вместо этого Storage. -
Key (Устаревшее) func(*fiber.Ctx) string Устаревшее: используйте вместо этого KeyGenerator. -

Примечание: Если пользовательское хранилище реализует интерфейс Storage, вы можете использовать пользовательское хранилище - для получения более подробной информации и примеров обратитесь к store.go.

Конфигурация по умолчанию

var ConfigDefault = Config{
    Max:        5,
    Expiration: 1 * time.Minute,
    KeyGenerator: func(c *fiber.Ctx) string {
        return c.IP()
    },
    LimitReached: func(c *fiber.Ctx) error {
        return c.SendStatus(fiber.StatusTooManyRequests)
    },
    SkipFailedRequests: false,
    SkipSuccessfulRequests: false,
    LimiterMiddleware: FixedWindow{},
}

Пользовательское хранилище/база данных

Вы можете использовать любой метод хранения из нашего пакета хранения.

storage := sqlite3.New() // Из github.com/gofiber/storage/sqlite3
app.Use(limiter.New(limiter.Config{
    Storage: storage,
}))