


http.MaxBytesReader ограничивает чтение входящего тела HTTP-запроса. При попытке прочитать больше заданного числа байт возвращается ошибка *http.MaxBytesError. На Mentoring.digital разберём небольшой обработчик, который различает превышение лимита и другую ошибку чтения.
package demo
import (
"errors"
"fmt"
"io"
"net/http"
)
func Ingest(w http.ResponseWriter, r *http.Request) {
const maxBody = 64 << 10
r.Body = http.MaxBytesReader(w, r.Body, maxBody)
defer r.Body.Close()
body, err := io.ReadAll(r.Body)
if err != nil {
var tooLarge *http.MaxBytesError
if errors.As(err, &tooLarge) {
http.Error(w, "body too large",
http.StatusRequestEntityTooLarge)
} else {
http.Error(w, "cannot read body",
http.StatusBadRequest)
}
return
}
fmt.Fprintf(w, "%d\n", len(body))
}В учебном примере предел равен 64 КиБ, то есть 65 536 байтам. Это выбранное для примера значение, а не универсальная рекомендация для любого API. Успешный ответ содержит число прочитанных байт. Разбор JSON и сохранение данных в этом обработчике не выполняются.
Ограничивающий объект устанавливается до io.ReadAll. Если сначала полностью прочитать тело, последующая обёртка уже не сможет ограничить это чтение.
MaxBytesReader предназначен для входящих HTTP-тел. В отличие от простого ограничения через io.LimitReader, превышение отмечается отдельной ошибкой. Проверка через errors.As позволяет распознать её и вернуть статус 413.
После записи ошибки обработчик завершает работу. Закрытие обёртки закрывает исходный reader. Здесь defer обеспечивает закрытие как при успешном чтении, так и при раннем выходе.
Значение r.ContentLength может быть неизвестным. Ограничение фактически прочитанных байт должно действовать независимо от наличия заявленного размера. Проверку заголовка можно использовать дополнительно, но решение о лимите в примере опирается на чтение потока.
ReadAll всё равно собирает разрешённое тело в памяти. Если API должен принимать большие данные потоком, отдельно проектируйте потоковую обработку и её ограничения.
Подготовьте пустое тело, тело ровно на границе и тело на один байт больше. Проверьте код ответа и отсутствие успешного ответа после ошибки. Повторите сценарий для запроса без заранее известной длины.
Такие обработчики можно изучать на курсах Go с практикой HTTP. Лимиты конкретного API и обработку ошибок разберите с наставником по Go.