31

In a middleware, I want to read request body to perform some checks. Then, the request is passed to the next middleware where the body will be read again. Here's what I do:

bodyBytes, _ := ioutil.ReadAll(req.Body)
req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
// use bodyBytes
// pass to next middleware

Now, req.Body.Close will do nothing. Will it break since the previous req.Body.Close implementation did some connection handling?

6
  • Related / possible duplicate of Golang read request body. Commented Oct 26, 2017 at 7:58
  • I read it. In the answer, the original body is not closed which is confusing. Commented Oct 26, 2017 at 8:06
  • 2
    At the server side you do not need to close the request body. Request.Body: "The Server will close the request body. The ServeHTTP Handler does not need to." Commented Oct 26, 2017 at 8:06
  • 1
    No, the original "close" is not lost. You merely assign a new value to the exported Request.Body field. This is not the only reference to the original body reader that needs to be closed. Commented Oct 26, 2017 at 9:40
  • 2
    the title is misleading, it should be reading request body instead Commented Jan 3, 2019 at 15:55

2 Answers 2

59

Will it break since the previous req.Body.Close implementation did some connection handling?

No.

But your code is buggy: You should close the req.Body once you are done reading all of it. Then you construct a new ReadCloser as you did and hand this to the next middleware (which itself or stuff further down is responsible for closing is.)

bodyBytes, _ := ioutil.ReadAll(req.Body)
req.Body.Close()  //  must close
req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. Perhaps, I should've rephrased my question since I'd like to get some understanding. In golang client, I close response body to get connection back into the pool for subsequent reuse in other request (correct me if I'm wrong). What does req.body.close do in the server at all?
I doubt that there is a simple answer. First it might not do anything in the server. On the client it is difficult too whether a connection is reused depends more on what client and server agree to do and less on you closing the body. But: of course you must close the original body. I'll update my answer.
At the server side you do not need to close the request body. Request.Body: "The Server will close the request body. The ServeHTTP Handler does not need to."
@Sergey I do not understand. You should close req.Body, even if reading from it produced an error. This is unrelated. Are you thinking of not closing of the request itself produces an error?
Upon looking at server code, the server keeps its own pointer to the Body, so it will always close the original body itself, at least that's how it seemed. Hence, does it matter that we close it here?
|
7

No need to close the request body in HTTP handler. Stdlib does that.

I recommend using this non-blocking version of the code in the middleware:

var b bytes.Buffer
r.Body = io.NopCloser(io.TeeReader(r.Body, &b))
  • copies the request body into the buffer as it's read by HTTP handler
  • doesn't slow down the handler on bigger request bodies

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.