Repository: go
Issue: net/http: remote end of long POST request randomly closes when using http2
Labels: NeedsInvestigation

### Go version

go1.20.5

### Output of `go env` in your module/workspace:

```shell
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/root/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.5"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1695464211=/tmp/go-build -gno-record-gcc-switches"
```


### What did you do?

I have two applications where the client application makes a HTTP/2 POST request to a server application.

The request is kept open permanently, effectively creating a bidirectional socket. In our case the client application continuously reads JSONL from the response body.

The server application receives the request and occasionally (just a couple times per day) writes some JSONL to the response body.

Equivalent code for the client application:
```golang
func main() {
	client := &http.Client{ /* HTTP2 transport */ }
	reader, writer := io.Pipe()
	encoder := json.NewEncoder(writer)
	go func() {
		encoder.Encode(/* some data */)
		// more data may be sent in the future so writer is never closed
	}()
	response, err := this.client.Post(url, content_type, reader)
	defer response.Body.Close()
	decoder := json.NewDecoder(response.Body)
	for {
		var msg map[string]any
		decoder.Decode(&msg)
	}
}
```
Equivalent code for the server application:
```golang
func main() {
	server := &http.Server{Addr: ":12345"}
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		decoder := json.NewDecoder(r.Body)
		go func() {
			encoder := json.NewEncoder(w)
			for {
				time.Sleep(time.Hour * 10)
				encoder.Encode(/* some data */)
				w.(http.Flusher).Flush()
			}
		}()
		defer log.Println("Client disconnected") // never happens
		// likely because request body is never terminated
		for {
			var msg map[string]any
			decoder.Decode(&msg)
		}
	})
	server.ListenAndServeTLS(certificate, keyfile)
}
```

### What did you see happen?

The two applications are able to communicate fine for hours/days/weeks but every now and then the response body becomes closed on the server for unknown reasons, resulting in `short write` errors.

I've tried to debug the issue by logging reads with `io.TeeReader` and writes with `io.MultiWriter`.  The logs show that  writes are attempted. JSONL is in fact sent over the wire as confirmed with `tcpdump` (even with SSL encryption, large blobs of data are easy to spot) despite `short write` errors. My guess is that only part of the JSONL is written, explaining the errors I am seeing.

However, none of the bytes appearing on the wire are read by the client, nothing shows up in the log and reads never return EOF. This means the client will patiently wait forever, oblivious of the fact that something is wrong.

Is there some built-in timeout I'm not aware of?

### What did you expect to see?

For the applications to continue talking to each other.