Есть ли способ использовать один и тот же запрос.Body в нескольких обработчиках без ручного написания большого количества кода или мне нужно изменить способ, которым я это делаю?

Эта замечательная статья здесь: https://www.alexedwards.net/blog/how-to-properly-parse-a-json-request-body очень хорошо объясняет, как написать обработчик Golang.

Мне нужно использовать два обработчика один за другим, только если первый выдает ошибку.

Нравится:

func main() {
    r := chi.NewRouter()

    r.Post("/api", MyHandlers)
}

func MyHandlers(w http.ResponseWriter, r *http.Request) {

    err := DoSomething(w, r)

    if err != nil {
        println("OMG! Error!")
        DoSomethingWithThisOneInstead(w, r)
    }

}

func DoSomething(w http.ResponseWriter, r *http.Request) error {
    // here I need to read request's Body
    // and I can use io.TeeReader()
    // and I can use all the code in the amazing article example
    // but I don't want to, because it's a lot of code to maintain
    res, err := myLibrary.DoSomething(requestBody)
    if err != nil {
        return err
    }
    render.JSON(w, r, res) // go-chi "render" pkg
    return nil
}

func DoSomethingWithThisOneInstead(w http.ResponseWriter, r *http.Request) {
    // here I need to read request's Body again!
    // and I can use all the code in the amazing article example
    // but I don't want to, because it's a lot of code to maintain
    anotherLibrary.DoSomethingElse.ServeHTTP(w, r)
}
  1. Есть ли другой метод вместо того, чтобы читать дважды или более одно и то же request.Body?

  2. Есть ли способ избежать написания всего этого кода в статье (который необходимо поддерживать) и использования библиотек с открытым исходным кодом, которые делают это лучше и пересматриваются тысячами более умных людей, чем я?

  3. Е.Г.: Могу ли я использовать go-chi метод?

1 ответ

Уберите байты и используйте по мере необходимости:

func MyHandlers(w http.ResponseWriter, r *http.Request) {
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
       // handle error
    }
    r.Body.Close()

    r.Body = ioutil.NopCloser(bytes.NewReader(body))
    err := DoSomething(w, r)

    if err != nil {
        println("OMG! Error!")
        r.Body = ioutil.NopCloser(bytes.NewReader(body))
        DoSomethingWithThisOneInstead(w, r)
    }

}
Другие вопросы по тегам