search
LoginSignup
1

More than 3 years have passed since last update.

posted at

GoのHTTPサーバのミドルウェアでリクエストボディを読み取る

ミドルウェアでリクエストボディを読み取ったあと、次のハンドラでもリクエストボディを読み取れるようにしておきたい場合があります。

一旦iouti.ReadAll()で取得したリクエストボディの中身(以下の例では変数buf)を元にioutil.NopColoser()io.ReadCloserを作って、Request.Bodyにセットしなおすことで、次のハンドラでも読み取れるようになります。

func middleware(h http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        ...
        buf, err := ioutil.ReadAll(r.Body)
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            return
        }

        r.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
        ...
        h(w, r)
        return
    }
}

ioutil.NopColoserは次のようにClose()を呼び出しても何もしない実装になっています。

type nopCloser struct {
    io.Reader
}

func (nopCloser) Close() error { return nil }

// NopCloser returns a ReadCloser with a no-op Close method wrapping
// the provided Reader r.
func NopCloser(r io.Reader) io.ReadCloser {
    return nopCloser{r}
}

labstack/echoのmiddlewareパッケージにあるBodyDumpWithConfigでも同じようなことしている箇所がありました。
https://github.com/labstack/echo/blob/6d9e043284aea2d07f5fcaf0d3a424eb7d9f6109/middleware/body_dump.go#L68-L73

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1