Documentation
¶
Overview ¶
Package httpx provides centralized outbound HTTP transport tuning for the bentoolkit. It exposes a helper for constructing a consistently configured *http.Transport so every HTTP client in the codebase shares the same connection-pool limits, timeouts, and HTTP/2 behavior, and a shared redirect policy, CredentialRedirectPolicy, that keeps credential headers from following a redirect to another host or to plain http.
The package depends only on the Go standard library; it intentionally adds no third-party imports.
Index ¶
Constants ¶
const ( // MaxBodyBytes is the maximum number of bytes that should be read from an // HTTP response body. Callers are expected to wrap response bodies with an // io.LimitReader (or http.MaxBytesReader) bounded by this value to guard // against unbounded memory growth from oversized or malicious responses. MaxBodyBytes int64 = 10 * 1024 * 1024 // 10 MiB // EnvDisableHTTP2 is the name of the environment variable that, when set to // "1", forces BuildTransport to disable HTTP/2 negotiation. This provides an // operational escape hatch for environments where HTTP/2 misbehaves. EnvDisableHTTP2 = "BENTOO_DISABLE_HTTP2" // DefaultResponseHeaderTimeout bounds how long a transport built here // waits for response headers after the request is written. A server that // accepts the connection but never answers ends the attempt as a timeout // instead of holding it until the whole-request timeout. DefaultResponseHeaderTimeout = 30 * time.Second )
Variables ¶
var CredentialHeaders = []string{"Authorization", "X-Api-Key", "X-Auth-Token", "Private-Token"}
CredentialHeaders are the request headers that carry a credential, in canonical form ("PRIVATE-TOKEN" canonicalises to "Private-Token"). They are the headers bentoolkit expands ${VAR} credentials into and the ones its GitHub, GitLab and LLM clients authenticate with.
var ErrInsecureRedirect = errors.New("insecure redirect")
ErrInsecureRedirect is returned by CredentialRedirectPolicy when following a redirect would send a credential from https to plain http.
var ErrResponseTooLarge = errors.New("response body too large")
ErrResponseTooLarge is returned when an HTTP response body exceeds the MaxBodyBytes cap. It lives here, not in a caller, so the autoupdate and the provider paths share one value and errors.Is matches it whichever package raised it (internal/common/provider cannot import internal/autoupdate).
Functions ¶
func BuildTransport ¶
BuildTransport returns a freshly constructed *http.Transport tuned with the bentoolkit's standard connection-pool limits and timeouts.
The returned transport sets MaxIdleConnsPerHost, MaxConnsPerHost, IdleConnTimeout, TLSHandshakeTimeout, ExpectContinueTimeout and ResponseHeaderTimeout (DefaultResponseHeaderTimeout), enables ForceAttemptHTTP2, and routes requests through http.ProxyFromEnvironment so HTTP_PROXY, HTTPS_PROXY and NO_PROXY are honoured. ProxyFromEnvironment reads the environment once per process and never proxies loopback hosts.
When the environment variable named by EnvDisableHTTP2 is set to "1", HTTP/2 is disabled: ForceAttemptHTTP2 is set to false and TLSNextProto is set to a non-nil empty map, which is the standard-library idiom for opting out of automatic HTTP/2 upgrades.
Each call returns an independent transport; callers own the returned value and may mutate it further before use.
func BuildTransportHTTP1 ¶
BuildTransportHTTP1 returns a transport identical to BuildTransport's except that HTTP/2 is always disabled, regardless of EnvDisableHTTP2.
Some WAF-fronted upstreams (notably Cloudflare) fingerprint the HTTP/2 connection preface and challenge Go's standard-library client with an HTTP 403 interstitial no matter what User-Agent it sends, while serving the exact same request over HTTP/1.1. This transport is the escape hatch used to retry such a request; see the HTTP/1.1 fallback in the autoupdate HTTP client.
func ClassifyBodyReadError ¶
ClassifyBodyReadError maps an error returned while reading an HTTP response body to a domain error. When the read tripped an http.MaxBytesReader cap the standard library yields an *http.MaxBytesError; this is translated into an error wrapping ErrResponseTooLarge that carries the limit. Any other non-nil error is returned unchanged, and a nil error yields nil.
func CredentialRedirectPolicy ¶
CredentialRedirectPolicy is an http.Client.CheckRedirect policy that never lets a credential header follow a redirect somewhere it was not sent to:
- A chain stops after 10 redirects, as net/http's default policy does.
- An https request that carried a credential header refuses a redirect to an http URL with an error wrapping ErrInsecureRedirect that names the target host. It reads the ORIGINAL request, so it holds even when an earlier hop already changed host and dropped the headers.
- Once the chain has left the original hostname, on this hop or an earlier one, every credential header is deleted and the redirect followed. Hostnames compare case-insensitively and exactly; the port is ignored.
Rule 3 reads the whole chain because net/http copies the INITIAL request's headers onto every hop (client.go, makeHeadersCopier): a header deleted on one hop is back on the next. Go strips Authorization on a cross-domain hop but not X-Api-Key or Private-Token, and never refuses https to http. The policy never logs or returns a header value.
Types ¶
This section is empty.