mirror of
https://github.com/therootcompany/golib.git
synced 2026-04-24 12:48:00 +00:00
fix: split connection and download timeouts in httpcache
ConnTimeout (default 5s) caps TCP connect + TLS handshake via net.Dialer and Transport.TLSHandshakeTimeout. Timeout (default 5m) caps the overall request including body read. Previously a single 30s timeout covered both, which was too short for large downloads and too long for connection failures.
This commit is contained in:
parent
86ffa2fb23
commit
d0a5e0a9d2
@ -3,13 +3,17 @@ package httpcache
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultTimeout = 30 * time.Second
|
const (
|
||||||
|
defaultConnTimeout = 5 * time.Second // TCP connect + TLS handshake
|
||||||
|
defaultTimeout = 5 * time.Minute // overall including body read
|
||||||
|
)
|
||||||
|
|
||||||
// Syncer is implemented by any value that can fetch a remote resource and
|
// Syncer is implemented by any value that can fetch a remote resource and
|
||||||
// report whether it changed. Both *Cacher and *gitshallow.Repo satisfy this.
|
// report whether it changed. Both *Cacher and *gitshallow.Repo satisfy this.
|
||||||
@ -43,7 +47,8 @@ func (NopSyncer) Fetch() (bool, error) { return false, nil }
|
|||||||
type Cacher struct {
|
type Cacher struct {
|
||||||
URL string
|
URL string
|
||||||
Path string
|
Path string
|
||||||
Timeout time.Duration // 0 uses 30s
|
ConnTimeout time.Duration // 0 uses 5s; caps TCP connect + TLS handshake
|
||||||
|
Timeout time.Duration // 0 uses 5m; caps overall request including body read
|
||||||
MaxAge time.Duration // 0 disables; skip HTTP if file mtime is within this
|
MaxAge time.Duration // 0 disables; skip HTTP if file mtime is within this
|
||||||
MinInterval time.Duration // 0 disables; skip HTTP if last Fetch attempt was within this
|
MinInterval time.Duration // 0 disables; skip HTTP if last Fetch attempt was within this
|
||||||
Username string // Basic Auth — not forwarded on redirects
|
Username string // Basic Auth — not forwarded on redirects
|
||||||
@ -86,6 +91,10 @@ func (c *Cacher) Fetch() (updated bool, err error) {
|
|||||||
}
|
}
|
||||||
c.lastChecked = time.Now()
|
c.lastChecked = time.Now()
|
||||||
|
|
||||||
|
connTimeout := c.ConnTimeout
|
||||||
|
if connTimeout == 0 {
|
||||||
|
connTimeout = defaultConnTimeout
|
||||||
|
}
|
||||||
timeout := c.Timeout
|
timeout := c.Timeout
|
||||||
if timeout == 0 {
|
if timeout == 0 {
|
||||||
timeout = defaultTimeout
|
timeout = defaultTimeout
|
||||||
@ -102,20 +111,26 @@ func (c *Cacher) Fetch() (updated bool, err error) {
|
|||||||
req.Header.Set("If-Modified-Since", c.lastMod)
|
req.Header.Set("If-Modified-Since", c.lastMod)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transport := &http.Transport{
|
||||||
|
DialContext: (&net.Dialer{Timeout: connTimeout}).DialContext,
|
||||||
|
TLSHandshakeTimeout: connTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
var client *http.Client
|
var client *http.Client
|
||||||
if c.Username != "" {
|
if c.Username != "" {
|
||||||
req.SetBasicAuth(c.Username, c.Password)
|
req.SetBasicAuth(c.Username, c.Password)
|
||||||
// Strip auth before following any redirect — presigned URLs (e.g. R2)
|
// Strip auth before following any redirect — presigned URLs (e.g. R2)
|
||||||
// must not receive our credentials.
|
// must not receive our credentials.
|
||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
|
Transport: transport,
|
||||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
req.Header.Del("Authorization")
|
req.Header.Del("Authorization")
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client = &http.Client{Timeout: timeout}
|
client = &http.Client{Timeout: timeout, Transport: transport}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user