Files
gopeed/pkg/download/extension_git_transport.go
T

63 lines
1.9 KiB
Go

package download
import (
"context"
"net"
"net/http"
"time"
gitclient "github.com/go-git/go-git/v5/plumbing/transport/client"
githttp "github.com/go-git/go-git/v5/plumbing/transport/http"
)
func init() {
// go-git exposes a process-wide protocol registry. Register once during
// initialization, rather than changing it during concurrent clones. Proxy
// settings still come from each clone's ProxyOptions.
transport := githttp.NewClient(newExtensionGitHTTPClient(10*time.Second, 60*time.Second))
gitclient.InstallProtocol("http", transport)
gitclient.InstallProtocol("https", transport)
}
func newExtensionGitHTTPClient(connectTimeout, idleTimeout time.Duration) *http.Client {
dialer := &net.Dialer{Timeout: connectTimeout, KeepAlive: 30 * time.Second}
// A socket read deadline must apply to one transfer, rather than a shared
// HTTP/2 connection carrying traffic from other requests.
protocols := new(http.Protocols)
protocols.SetHTTP1(true)
return &http.Client{Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
conn, err := dialer.DialContext(ctx, network, address)
if err != nil {
return nil, err
}
return &gitIdleConn{Conn: conn, timeout: idleTimeout}, nil
},
TLSHandshakeTimeout: connectTimeout,
IdleConnTimeout: idleTimeout,
Protocols: protocols,
}}
}
type gitIdleConn struct {
net.Conn
timeout time.Duration
}
func (c *gitIdleConn) Read(p []byte) (int, error) {
if err := c.Conn.SetReadDeadline(time.Now().Add(c.timeout)); err != nil {
return 0, err
}
return c.Conn.Read(p)
}
// Refresh an already-pending read when a pooled HTTP/1 connection starts the
// next request; time spent idle in the pool must not consume its read allowance.
func (c *gitIdleConn) Write(p []byte) (int, error) {
if err := c.Conn.SetReadDeadline(time.Now().Add(c.timeout)); err != nil {
return 0, err
}
return c.Conn.Write(p)
}