1
0
mirror of https://github.com/golang/go synced 2024-11-21 21:14:47 -07:00

Fix blocking finishAsyncByteRead.Read method

Chunked http requests that do not provide the first byte within 200ms
utilize finishAsyncByteRead. The Read method never returns io.EOF and
will block upon second call because the channel is empty.

This PR follows the same pattern as used by byteReader to return io.EOF
in the first call if err is nil and for all subsequent calls.
This commit is contained in:
Ed Schouten 2021-06-17 00:08:30 +02:00
parent 0e67ce3d28
commit a149748bde

View File

@ -235,7 +235,7 @@ func (t *transferWriter) probeRequestBody() {
// assuming that this is ContentLength == -1
// (unknown), which means we'll send a
// "Transfer-Encoding: chunked" header.
t.Body = io.MultiReader(finishAsyncByteRead{t}, t.Body)
t.Body = io.MultiReader(&finishAsyncByteRead{tw: t}, t.Body)
// Request that Request.Write flush the headers to the
// network before writing the body, since our body may not
// become readable until it's seen the response headers.
@ -1060,18 +1060,26 @@ func parseContentLength(cl string) (int64, error) {
// finishAsyncByteRead finishes reading the 1-byte sniff
// from the ContentLength==0, Body!=nil case.
type finishAsyncByteRead struct {
tw *transferWriter
tw *transferWriter
done bool
}
func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
func (fr *finishAsyncByteRead) Read(p []byte) (n int, err error) {
if fr.done {
return 0, io.EOF
}
if len(p) == 0 {
return
}
fr.done = true
rres := <-fr.tw.ByteReadCh
n, err = rres.n, rres.err
if n == 1 {
p[0] = rres.b
}
if err == nil {
err = io.EOF
}
return
}