FiberMiddleTechnical
Как валидировать и ограничивать размер request body, чтобы не получить DoS?
BodyLimit в fiber.Config ограничивает размер тела глобально; для стриминга добавляйте io.LimitReader явно. Rate-limiting middleware предотвращает DoS на уровне числа запросов.
Глобальный лимит тела через fiber.Config
Самый простой способ защититься от DoS с огромным телом — установить BodyLimit при создании приложения. Fiber возвращает 413 Request Entity Too Large до того, как тело попадает в хендлер:
app := fiber.New(fiber.Config{
BodyLimit: 1 * 1024 * 1024, // 1 MB по умолчанию
})
Переопределение лимита для конкретного маршрута
Иногда один эндпоинт (upload) требует большего лимита, а остальные — меньшего:
// Глобально: 1 MB
app := fiber.New(fiber.Config{
BodyLimit: 1 * 1024 * 1024,
})
// Для upload: переопределяем через RequestCtx
app.Post("/upload", func(c *fiber.Ctx) error {
// Увеличиваем лимит только для этого запроса
c.Request().SetMaxBodySize(50 * 1024 * 1024)
file, err := c.FormFile("file")
if err != nil {
return c.Status(fiber.StatusBadRequest).
JSON(fiber.Map{"error": "invalid file"})
}
if file.Size > 10*1024*1024 {
return c.Status(fiber.StatusRequestEntityTooLarge).
JSON(fiber.Map{"error": "file too large"})
}
return c.SaveFile(file, "./uploads/"+file.Filename)
})
Валидация Content-Length заранее
app.Use(func(c *fiber.Ctx) error {
const maxSize = 1 * 1024 * 1024 // 1 MB
if c.Request().Header.ContentLength() > maxSize {
return c.Status(fiber.StatusRequestEntityTooLarge).
JSON(fiber.Map{"error": "request too large"})
}
return c.Next()
})
Rate-limiting для защиты от DoS
import "github.com/gofiber/fiber/v2/middleware/limiter"
// Глобальный rate-limit: 100 запросов/минуту на IP
app.Use(limiter.New(limiter.Config{
Max: 100,
Expiration: 1 * time.Minute,
KeyGenerator: func(c *fiber.Ctx) string {
return c.IP() // используем реальный IP (с TrustedProxies)
},
LimitReached: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusTooManyRequests).
JSON(fiber.Map{"error": "rate limit exceeded"})
},
}))
// Более жёсткий лимит на auth эндпоинты
app.Post("/auth/login", limiter.New(limiter.Config{
Max: 5,
Expiration: 1 * time.Minute,
}), loginHandler)
Защита от slow-body атак (ReadTimeout)
app := fiber.New(fiber.Config{
BodyLimit: 1 * 1024 * 1024,
ReadTimeout: 5 * time.Second, // клиент должен отправить тело за 5 сек
})
Подводные камни
- BodyLimit не работает для chunked encoding без Content-Length: если клиент не посылает заголовок
Content-Length, BodyLimit срабатывает только при достижении лимита при чтении — добавьтеReadTimeoutкак второй рубеж. - SetMaxBodySize в хендлере слишком поздно: вызов после частичного чтения тела не имеет эффекта; вызывайте до любого чтения.
- Rate-limit по IP без TrustedProxies: без корректной настройки все запросы через балансировщик имеют один IP — rate-limit работает как глобальный, а не per-client.
- Отсутствие лимита на количество полей формы: multipart/form-data с миллионами полей вызывает OOM; ограничивайте количество частей.
- В памяти vs. диск для больших файлов: Fiber/Fasthttp буферизует тело в памяти; для файлов > 10 MB используйте стриминг напрямую в хранилище.
- Content-Type без валидации: злоумышленник может послать JSON-тело с
Content-Type: multipart/form-data; проверяйте Content-Type явно в middleware.
Common mistakes
- Отвечать определением без production-сценария.
- Не называть runtime boundary, security boundary или failure mode.
- Игнорировать версию API, observability и тестовую проверку.
What the interviewer is testing
- Объясняет механизм своими словами и без выдуманных API.
- Называет реальные риски, диагностику и критерий корректности.
- Связывает ответ с текущей документацией и миграционными ограничениями.