Documentation
¶
Overview ¶
Package httpclient builds the HTTP transports shared by Entire's client binaries (git-remote-entire, entiredb, entire-deploy). Centralizing transport construction means one place to honor cross-cutting knobs like ENTIRE_CONNECT_TIMEOUT_SECONDS — without forcing callers through a single *http.Client constructor, since they legitimately differ in CheckRedirect, per-client Timeout, and request-level wrapping.
Index ¶
- Constants
- Variables
- func CheckSecureRedirect(req *http.Request, via []*http.Request) error
- func DialTimeout() time.Duration
- func DiscoveryDialTimeout() time.Duration
- func New(options Options) *http.Client
- func NewDiscoveryTransport(skipTLSVerify bool) http.RoundTripper
- func NewTransport(skipTLSVerify bool) http.RoundTripper
- func WithSecureRedirects(client *http.Client) *http.Client
- type Options
- type UserAgentTransport
Constants ¶
const ( // SchemeHTTPS is the secure scheme required for production credential transport. SchemeHTTPS = "https" // SchemeHTTP is permitted only by callers' explicit insecure-origin policies. SchemeHTTP = "http" )
const DefaultDialTimeout = 4 * time.Second
DefaultDialTimeout is the per-request connection setup budget: DNS, TCP, the proxy CONNECT when a proxy is configured, and TLS. Short by default so failover paths skip dead nodes quickly, but long enough to absorb a slow initial connect (cold DNS, TLS-fronting LB, distant region) that a tighter budget would trip; override via ENTIRE_CONNECT_TIMEOUT_SECONDS on slow links (e.g. satellite) where even this trips before the node answers.
const DefaultDiscoveryDialTimeout = 10 * time.Second
DefaultDiscoveryDialTimeout is the connection setup budget for the initial replica-discovery request — the cold info/refs probe to the cluster entry domain that answers "which nodes serve this repo". It is deliberately longer than DefaultDialTimeout: this first contact often pays a cold DNS + TLS handshake to a possibly-distant entry LB, and unlike replica failover there is no second node to roll to, so tripping here fails the whole clone/fetch. Replica failover keeps the short DefaultDialTimeout so dead nodes are still skipped quickly.
An explicit ENTIRE_CONNECT_TIMEOUT_SECONDS overrides this too: a user who sets it gets that one value for every connect, discovery included.
const EnvConnectTimeout = "ENTIRE_CONNECT_TIMEOUT_SECONDS"
EnvConnectTimeout is the env var that overrides every connect timeout.
Variables ¶
var ( // ErrRequestPolicy identifies a request refused for security policy reasons. ErrRequestPolicy = errors.New("request rejected by policy") // ErrRedirectPolicy identifies a redirect rejected by the shared security policy. ErrRedirectPolicy error = &policyError{msg: "redirect refused", parent: ErrRequestPolicy} // ErrInsecureRedirect identifies a redirect that would leave HTTPS. ErrInsecureRedirect error = &policyError{msg: "refusing redirect from HTTPS to an insecure scheme", parent: ErrRedirectPolicy} // ErrTooManyRedirects identifies a redirect chain exceeding the hop limit. // A loop is an availability failure, not a security rejection, so it does // not match ErrRequestPolicy: callers treat it like any other node failure. ErrTooManyRedirects = errors.New("stopped after " + strconv.Itoa(maxRedirects) + " redirects") )
var ErrConnectTimeout = errors.New("connection setup timed out")
ErrConnectTimeout reports that a request could not obtain a usable connection within its connect budget.
Functions ¶
func CheckSecureRedirect ¶ added in v0.11.5
CheckSecureRedirect is a CheckRedirect policy that limits redirect chains and refuses to leave HTTPS once reached. Host restrictions belong to the caller.
It returns ErrTooManyRedirects once via holds the hop limit, and ErrInsecureRedirect when req is not HTTPS but any request in via was. Only via counts as having reached HTTPS: req is the proposed next hop, so an HTTP → HTTPS upgrade is allowed and anything after it must stay HTTPS.
func DialTimeout ¶
DialTimeout returns the connect timeout for ordinary requests (and replica failover): the ENTIRE_CONNECT_TIMEOUT_SECONDS override if set, else DefaultDialTimeout.
func DiscoveryDialTimeout ¶ added in v0.7.8
DiscoveryDialTimeout returns the connect budget for the discovery probe. When ENTIRE_CONNECT_TIMEOUT_SECONDS is set it wins outright (the user's chosen value applies to every connect); otherwise it falls back to the more patient DefaultDiscoveryDialTimeout rather than DefaultDialTimeout.
func New ¶ added in v0.11.5
New returns an HTTP client that always rejects HTTPS downgrades and caps redirect chains. It preserves Go's sensitive-header handling and composes any supplied callback.
func NewDiscoveryTransport ¶ added in v0.7.8
func NewDiscoveryTransport(skipTLSVerify bool) http.RoundTripper
NewDiscoveryTransport is NewTransport with the longer discovery connect budget (DiscoveryDialTimeout). Use it for the initial replica-discovery probe; see DefaultDiscoveryDialTimeout for why it is more patient.
func NewTransport ¶
func NewTransport(skipTLSVerify bool) http.RoundTripper
NewTransport builds a transport with the configured connect budget and a baseline TLS config. Callers wrap the returned transport with their own RoundTripper as needed (e.g. debug logging) and assemble their own *http.Client around it.
func WithSecureRedirects ¶ added in v0.11.5
WithSecureRedirects returns a copy of client whose CheckRedirect enforces CheckSecureRedirect around the client's own callback. The callback runs first, on every hop, and can only add restrictions:
- http.ErrUseLastResponse is returned unchanged, so a callback can still expose a 3xx response without following it;
- otherwise a shared-policy rejection of the proposed URL wins over the callback's own error, so a downgrade always reports ErrInsecureRedirect;
- if the callback permits the hop, the possibly rewritten req.URL is checked again, and the callback cannot undo an HTTPS upgrade.
The callback also runs on hops the shared policy then rejects, so it must not have external side effects; changes to a rejected req are discarded because that request is never sent. Callbacks must not call CheckSecureRedirect themselves. A nil client uses http.DefaultClient. Transport, timeout and jar are preserved; neither the supplied client nor the default client is mutated.
Types ¶
type Options ¶ added in v0.11.5
type Options struct {
Transport http.RoundTripper
Timeout time.Duration
CheckRedirect func(*http.Request, []*http.Request) error
}
Options configures an HTTP client without allowing callers to omit the shared redirect policy. A nil Transport uses http.DefaultTransport and a zero Timeout means no timeout, as on http.Client. CheckRedirect runs before the shared policy on every hop and can only add restrictions; see WithSecureRedirects for the exact composition.
type UserAgentTransport ¶ added in v0.7.4
type UserAgentTransport struct {
Next http.RoundTripper
UA string
}
UserAgentTransport wraps another http.RoundTripper and stamps the User-Agent header on every outgoing request so the server can attribute traffic to the calling binary. Callers that already set User-Agent are overwritten: the wrapper exists to give the binary a single identity in upstream access logs, not to be overridden per request.
The wrapper clones the request before mutating headers so the caller's original *http.Request is left untouched — important for retries and for callers that hold a reference after Do returns.
Concurrent use is safe iff Next is safe for concurrent use.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package httpclienttest provides redirect regression fixtures for HTTP clients.
|
Package httpclienttest provides redirect regression fixtures for HTTP clients. |