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.