Fix connection reuse in splithttp HTTP/1.1 (#3485)

This commit is contained in:
mmmray 2024-07-01 05:30:34 +02:00 committed by GitHub
parent 079d0bd8a9
commit c6a57b2cc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,7 @@
package splithttp
import (
"bytes"
"context"
gotls "crypto/tls"
"io"
@ -263,6 +264,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
return
}
req.ContentLength = int64(chunk.Len())
req.Header = transportConfiguration.GetRequestHeader()
if httpClient.isH2 {
@ -280,11 +282,19 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
return
}
} else {
var err error
var uploadConn any
for i := 0; i < 5; i++ {
// stringify the entire HTTP/1.1 request so it can be
// safely retried. if instead req.Write is called multiple
// times, the body is already drained after the first
// request
requestBytes := new(bytes.Buffer)
common.Must(req.Write(requestBytes))
for {
uploadConn = httpClient.uploadRawPool.Get()
if uploadConn == nil {
newConnection := uploadConn == nil
if newConnection {
uploadConn, err = httpClient.dialUploadConn(context.WithoutCancel(ctx))
if err != nil {
errors.LogInfoInner(ctx, err, "failed to connect upload")
@ -293,18 +303,21 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
}
}
err = req.Write(uploadConn.(net.Conn))
_, err = uploadConn.(net.Conn).Write(requestBytes.Bytes())
// if the write failed, we try another connection from
// the pool, until the write on a new connection fails.
// failed writes to a pooled connection are normal when
// the connection has been closed in the meantime.
if err == nil {
break
} else if newConnection {
errors.LogInfoInner(ctx, err, "failed to send upload")
uploadPipeReader.Interrupt()
return
}
}
if err != nil {
errors.LogInfoInner(ctx, err, "failed to send upload")
uploadPipeReader.Interrupt()
return
}
httpClient.uploadRawPool.Put(uploadConn)
}
}()