Repository: go
Issue: net/http: client fails when server closes connection before reading request body
Labels: NeedsInvestigation

<!--
Please answer these questions before submitting your issue. Thanks!
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.17.6 linux/amd64
</pre>

### Does this issue reproduce with the latest release?

Yes (go1.18beta2)

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/dustin/.cache/go-build"
GOENV="/home/dustin/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/dustin/.gvm/pkgsets/go1.15.14/global/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/dustin/.gvm/pkgsets/go1.15.14/global"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/dustin/.gvm/gos/go1.15.14"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/dustin/.gvm/gos/go1.15.14/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/dustin/tmp/server/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build635155538=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?

https://go.dev/play/p/QW2sddZp7XY

tl;dr: when a server sends a response and closes the connection before reading the request body, net/http fails with an error.  We've observed this behavior with haproxy, and it appears to be allowed by RFC 7230:

>   A server MUST read
>   the entire request message body or close the connection after sending
>   its response, since otherwise the remaining data on a persistent
>   connection would be misinterpreted as the next request.  Likewise, a
>   client MUST read the entire response message body if it intends to
>   reuse the same connection for a subsequent request.

and

>   A client sending a message body SHOULD monitor the network connection
>   for an error response while it is transmitting the request.  If the
>   client sees a response that indicates the server does not wish to
>   receive the message body and is closing the connection, the client
>   SHOULD immediately cease transmitting the body and close its side of
>   the connection.

### What did you expect to see?

Successful HTTP response (307 Redirect)

The client should, on noting that it cannot write to the connection, check whether the data received on the connection constitutes a valid response, and if so return that response instead of an error.

### What did you see instead?

```
2009/11/10 23:00:00 Post "http://127.0.0.1:8080": write tcp 127.0.0.1:22845->127.0.0.1:8080: write: connection reset by peer
```

Looking at a packet dump of this behavior, it appears that when the server closes the socket, the client continues sending data, which generates RST frames from the server, which translate into the given error.  In fact, this all occurs before the server sends a FIN frame.