Middleware очищает request.Body

Имеем:

На роуте висит мидлварь, которая проверяет валидные ли пришли данные внутри json. Сам json, естественно в request.Body. Для того чтобы проверить данные в json-e, его нужно распаковать, что и делается в мидлвари. Но получается весьма неприятное поведение, при котором, после распаковки json-a, из Body, Body становится пустым и когда я делаю next.ServeHTTP(w,r), остальне контроллеры получают пустой request.Body.

Почему так просиходит, в принципе, понятно. А вот что с этим делать - не совсем.

Мне нужно, чтобы либо: мидлварь не очищала body после прочтения совсем, либо заполняла его обртно json-ом перед тем как передать управление другому контроллеру(HadlerFunc-у) либо мне нужен подход при котором json вообще не будет распаковываться для прочтения(здесь даже на ум ничего не приходит...это ж API и там нужно чтобы данне проверялись на валидность прежде сем пойти во внутренние функции сервера). Распаковывать json в мидлвари и перед передачей другому контроллеру запаковывать обратно выглядит не очень. Важно, что обьекты должны продолжать передаваться по ссылке.

В общем какой есть ИДИАМАТИЧИСКАЙ подход проверки валидности данных в json-e?

Такое в файле models(все не привожу дабы не перегружать. Там еще интерфейсы и интерфейсные функции)

type Entries struct {
    Number string `gorm:"number" json:"number"`
    Object *Contact `gorm:"object" json:"object,omitempty"`
    Error error `json:"error,omitempty" gorm:"-" `
}

type Contact struct {
    Number     string   `json:"num,omitempty"`
    Name       string   `json:"name,omitempty"`
    NumberList []string `json:"nlist,omitempty"`
}

func (j *Entries) UnpackEntries(data []byte) {
    err := json.Unmarshal(data, j)
    if err != nil {
        j.Error = err
        return
    }
}

Такое в controller-ах

func request(w http.ResponseWriter, r *http.Request) *models.Entries {
    req, err := io.ReadAll(r.Body)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        w.Write([]byte("Something wrong. Try later"))
    }
    e := &models.Entries{}
    //UnpackingEntries это как раз интерфейсная фунция которая 
    //вызывает метод func (j *Entries) UnpackEntries(data []byte)
    //см выше сам метод
    models.UnpackingEntries(e, req)
    return e
}

//проблемная мидлварь
func MW(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        r.Header.Set("Accept", "application/json")
        // Здесь r.Body содержит  отправленный серверу json
        e := request(w, r)
        use.Match(e, use.ENUM)
        if e.Error != nil {
            fmt.Fprintln(w, e)
            log.Println(e.Error, "for object", e.Object)
            return
        }
        // здесь r.Body не содержит отправленныйв серверу json.
        next.ServeHTTP(w, r)
    }
}

После мидлвари другие контроллеры тоже используют функцию request() но она уже дает ошибку Unexpected end of JSON


Ответы (1 шт):

Автор решения: Паша

Вот тут что-то похожее на ваш вопрос, только вместо пакета ioutil нужно использовать просто io.

→ Ссылка