Why does http.Client close body streams on performing the request?

Recently, I tackled a very odd behavior when passing a file handler as body to an HTTP POST request and performing the request subsequently, the file was closed afterwards.

After that, I tested around a bit and found out, that the body is indeed closed by the RountTripper of the http package on request.

Below, you can see a brief demonstration of the behavior.

package main

import (
	"fmt"
	"io"
	"net/http"
)

type dummy struct {
	IsClosed bool
}

func (d dummy) Read(p []byte) (n int, err error) {
	return 0, nil
}

func (d *dummy) Close() error {
	d.IsClosed = true
	return nil
}

func main() {
	d := dummy{}
	r, _ := http.NewRequest("POST", "http://localhost:80", &d)
	http.DefaultClient.Do(r)
	fmt.Println(d.IsClosed)
	// → true
}

I am actually very curious why the decision was made to close streams when performing a request on them passed as body. In my personal opinion, this is very counter intuitive and the program itself should have the responsibility to handle the streams closing state.

I also looked through the code where the close is performed but did not find any documentation why it is done this way. Would be really interesting to hear your opinion about that. If you know the reason why it is done this way, please let me know. :slightly_smiling_face:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.