1476120c7b
All upstream GET/HEAD and bearer-token requests used http.DefaultClient, which has no timeouts, so a slow or wedged upstream could pin a goroutine and connection indefinitely. Introduce a shared upstreamClient with dial, TLS-handshake and response-header timeouts (no overall Client timeout, so large artifact bodies can still stream, bounded by the request context). Refs #67
31 lines
947 B
Go
31 lines
947 B
Go
package proxy
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// upstreamClient is the shared HTTP client for all upstream requests.
|
|
//
|
|
// It deliberately sets no overall Client.Timeout: the proxy streams
|
|
// arbitrarily large artifacts and the total time is bounded by the request
|
|
// context instead. Instead it constrains the phases that must never hang —
|
|
// connect, TLS handshake, and time-to-first-response-header — so a slow or
|
|
// wedged upstream cannot pin a goroutine and connection indefinitely.
|
|
var upstreamClient = &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: http.ProxyFromEnvironment,
|
|
DialContext: (&net.Dialer{
|
|
Timeout: 10 * time.Second,
|
|
KeepAlive: 30 * time.Second,
|
|
}).DialContext,
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
ResponseHeaderTimeout: 30 * time.Second,
|
|
},
|
|
}
|