ceth
ceth

Reputation: 45285

How to get the request body in the middleware

I need to get the request body in the middleware. Something like:

return func(w http.ResponseWriter, req *http.Request) {

    data, err := handler(w, req)

    if err != nil {
        buf := new(bytes.Buffer)
        buf.ReadFrom(req.Body)
        s := buf.String()

But I get s == "" with POST request with body. Why and how can I fix it ?

Upvotes: 2

Views: 2727

Answers (1)

Zak
Zak

Reputation: 5898

You can only read the request body once, but you can read it once and create copies of what you read. Using either a tee reader

https://golang.org/pkg/io/#example_TeeReader

Or this answer:

https://stackoverflow.com/a/23077519/6376471

Both include reading the body into memory once, and then making a copy. So that when you consume it in the middleware, you reassign the copy to the request object before forwarding it to the handler.

For you something like:

return func (w http.ResponseWriter, req *http.Request) {
    buf, err := ioutil.ReadAll(r.Body) // handle the error
    rdr1 := ioutil.NopCloser(bytes.NewBuffer(buf))

    req.Body = rdr1
    data, err := handler(w, req)
    if err != nil {
        s := buf.String()
        // ... trimmed
    }
}

This obviously has all of the side effects of the request body into memory, what if the body is very large etc. And you middleware is taking away some control from the handlers etc.

Upvotes: 6

Related Questions