ошибка при декодировании json из request.Body

При расшифровке json из тела пост запроса таким кодом, то получаю ошибку декодирования. Причем судя по тексту ошибки, то ошибка не в этом методе , а далее в обработчиках graphql за методом h(w, r) .

func middlewareAuth(h http.HandlerFunc) http.HandlerFunc {
  return func(w http.ResponseWriter, r *http.Request) {

    var requestBody requestBody

    bytebody, err := ioutil.ReadAll(r.Body)
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        http.Error(w, "{\"errors\":[{\"message\":\"Request decode error!.\"}],\"data\":null}", 400)
        return
    }

    replaceChars := strings.NewReplacer("\n", "", "\r", "")
    strbody := replaceChars.Replace(string(bytebody))

    if len(strbody) > 0 {
        err := json.Unmarshal([]byte(strbody), &requestBody)
        if err != nil {
            w.WriteHeader(http.StatusBadRequest)
            http.Error(w, "{\"errors\":[{\"message\":\"Request decode error! please check your JSON formating. custom\"}],\"data\":null}", 400)
            return
        }
    }

    h(w, r)
  }
}

graphql выдает ошибку:

{
  "error": {
    "errors": [
      {
        "message": "json body could not be decoded: EOF"
      }
    ],
    "data": null
  }
}

Но если обрабатывать произвольный json в строке, то ошибок нет :

func middlewareAuth(h http.HandlerFunc) http.HandlerFunc {
  return func(w http.ResponseWriter, r *http.Request) {

    var requestBody requestBody

    var strbody string
    strbody = "{\"query\":\"custom\", \"token\":\"l7k8\"}"


    if len(strbody) > 0 {
        err := json.Unmarshal([]byte(strbody), &requestBody)
        if err != nil {
            w.WriteHeader(http.StatusBadRequest)
            http.Error(w, "{\"errors\":[{\"message\":\"Request decode error! please check your JSON formating. custom\"}],\"data\":null}", 400)
            return
        }
    }

    h(w, r)
  }
}

Не понимаю почему возникает ошибка, request я не модифицирую

помогите исправить ошибку


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

Автор решения: Senior Pomidor

из r.Body можно читать один раз. вы это делаете в коде ioutil.ReadAll(r.Body)

после, если прочитать еще раз, то получите ошибку. поэтому, вам нужно прочитать и записать обратно тоже самое.

bodyBytes, _ := ioutil.ReadAll(r.Body)
r.Body.Close()  //  must close
r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
→ Ссылка