From 4a0372ff05bc22613cea4f18c9814f269395ca45 Mon Sep 17 00:00:00 2001 From: Repinoid Date: Sat, 10 Oct 2026 19:14:47 +0300 Subject: [PATCH] =?UTF-8?q?chore(iot):=20=D0=BB=D0=B8=D0=BC=D0=B8=D1=82=20?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D0=B0=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D0=B0=20+=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=B8=D0=B7=D0=B2=D0=B5=D1=81=D1=82=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20+=20=D1=82=D0=B0=D0=B9=D0=BC?= =?UTF-8?q?=D0=B0=D1=83=D1=82=D1=8B=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=B0=20(=D0=AD=D1=82=D0=B0=D0=BF=205)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - decodeJSON: http.MaxBytesReader (64 КиБ) + DisallowUnknownFields; используется в Create/Update устройства. Ловит опечатки в полях (важно для Terraform). - http.Server: добавлены ReadTimeout=15с, WriteTimeout=60с, IdleTimeout=120с (был только ReadHeaderTimeout). --- cmd/iot-service/main.go | 5 +++++ internal/service/api/handler/devices.go | 5 ++--- internal/service/api/handler/handler.go | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/cmd/iot-service/main.go b/cmd/iot-service/main.go index 303ae38..12cd2b5 100644 --- a/cmd/iot-service/main.go +++ b/cmd/iot-service/main.go @@ -104,6 +104,11 @@ func run() int { Addr: ":" + cfg.APIPort, Handler: router, ReadHeaderTimeout: 10 * time.Second, + ReadTimeout: 15 * time.Second, + // WriteTimeout с запасом: admin-stats/telemetry отвечают через SQS/PG + // (внутренние таймауты до 15с). IdleTimeout — для keep-alive платформы. + WriteTimeout: 60 * time.Second, + IdleTimeout: 120 * time.Second, } // bridge + consumer — в фоне. diff --git a/internal/service/api/handler/devices.go b/internal/service/api/handler/devices.go index 703a0a0..c4bcc13 100644 --- a/internal/service/api/handler/devices.go +++ b/internal/service/api/handler/devices.go @@ -12,7 +12,6 @@ package handler import ( "crypto/rand" "encoding/hex" - "encoding/json" "errors" "net/http" "regexp" @@ -143,7 +142,7 @@ func (h *Handler) CreateIoTDevice(w http.ResponseWriter, r *http.Request) { } var req iotDeviceCreateRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + if err := decodeJSON(w, r, &req); err != nil { writeJSON(w, http.StatusBadRequest, errResp("invalid JSON: "+err.Error())) return } @@ -299,7 +298,7 @@ func (h *Handler) UpdateIoTDevice(w http.ResponseWriter, r *http.Request) { name := pathVar(r, "name") var req iotDeviceUpdateRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + if err := decodeJSON(w, r, &req); err != nil { writeJSON(w, http.StatusBadRequest, errResp("invalid JSON: "+err.Error())) return } diff --git a/internal/service/api/handler/handler.go b/internal/service/api/handler/handler.go index 22e817c..cf7c9f5 100644 --- a/internal/service/api/handler/handler.go +++ b/internal/service/api/handler/handler.go @@ -38,6 +38,21 @@ func writeJSON(w http.ResponseWriter, status int, v any) { _ = json.NewEncoder(w).Encode(v) } +// maxRequestBodyBytes — максимум размера тела запроса (устройства/метаданные +// небольшие; 64 КиБ с запасом). +const maxRequestBodyBytes = 64 * 1024 + +// decodeJSON читает JSON-тело с лимитом размера и запретом неизвестных полей +// (ревью 2026-10-10). MaxBytesReader защищает от раздутых тел; +// DisallowUnknownFields ловит опечатки в полях — критично для Terraform (лучше +// 400 с понятной ошибкой, чем молча проигнорированное поле). +func decodeJSON(w http.ResponseWriter, r *http.Request, v any) error { + r.Body = http.MaxBytesReader(w, r.Body, maxRequestBodyBytes) + dec := json.NewDecoder(r.Body) + dec.DisallowUnknownFields() + return dec.Decode(v) +} + // errResp возвращает структуру ошибки для JSON. func errResp(msg string) map[string]string { return map[string]string{"error": msg}