httpclient

package
v0.11.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 11 Imported by: 0

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

View Source
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"
)
View Source
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.

View Source
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.

View Source
const EnvConnectTimeout = "ENTIRE_CONNECT_TIMEOUT_SECONDS"

EnvConnectTimeout is the env var that overrides every connect timeout.

Variables

View Source
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")
)
View Source
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

func CheckSecureRedirect(req *http.Request, via []*http.Request) error

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

func DialTimeout() time.Duration

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

func DiscoveryDialTimeout() time.Duration

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

func New(options Options) *http.Client

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

func WithSecureRedirects(client *http.Client) *http.Client

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.

func (*UserAgentTransport) RoundTrip added in v0.7.4

func (t *UserAgentTransport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper.

Directories

Path Synopsis
Package httpclienttest provides redirect regression fixtures for HTTP clients.
Package httpclienttest provides redirect regression fixtures for HTTP clients.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL