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.