httpclient

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package httpclient provides a centralized HTTP client factory with preset configurations.

Index

Constants

View Source
const (
	// DefaultTimeout is the standard timeout for most HTTP requests (30s).
	DefaultTimeout = 30 * time.Second

	// LongTimeout is for operations that may take longer (60s).
	LongTimeout = 60 * time.Second
)

Preset timeout durations for common use cases.

Variables

This section is empty.

Functions

func New

func New(opts ...Option) *http.Client

New creates a new HTTP client with the given options. If no timeout is specified, DefaultTimeout (30s) is used.

func NewDefault

func NewDefault() *http.Client

NewDefault creates a new HTTP client with the default timeout (30s).

func NewForExternal

func NewForExternal(net NetworkProxyConfig, timeout time.Duration) *http.Client

NewForExternal builds a proxy-aware *http.Client with the given timeout, reading proxy settings from the supplied config. Used by every external integration (Prowlarr, SABnzbd, NZBLNK resolver, Arrs). Internal endpoints should NOT use this — call New() or use http.DefaultClient instead.

A nil net argument disables proxying.

func NewLong

func NewLong() *http.Client

NewLong creates a new HTTP client with a longer timeout (60s). Suitable for operations that may take longer, such as external API calls.

func RedactURLError

func RedactURLError(err error) error

RedactURLError strips the query string, fragment and userinfo from the URL embedded in a *url.Error before it can reach a log or an API response.

Indexer requests carry credentials as query parameters — an `apikey` on Newznab search/caps calls, and whatever the upstream indexer embeds in a Prowlarr-issued download URL. net/http reports transport failures as a *url.Error whose message is the full request URL, so wrapping such an error unmodified publishes the credential wherever the caller logs or renders it.

The wrapped cause is preserved, so errors.Is/As against the underlying error (context.DeadlineExceeded, net.Error, ...) behave as before. Scheme, host and path are kept — they are what makes the error diagnosable.

func SafeDownloadCheckRedirect

func SafeDownloadCheckRedirect(maxRedirects int) func(req *http.Request, via []*http.Request) error

SafeDownloadCheckRedirect returns a CheckRedirect function that permits redirects up to maxRedirects (default 10) and re-validates each redirect target per hop with ValidateDownloadURL — the same literal-IP-only rule (DNS hostnames NOT resolved — see ValidateDownloadURL). It also redacts sensitive credentials (X-Api-Key, Authorization) when redirecting away from the ORIGINAL request origin (scheme + host, case-insensitive); that redaction governs request headers, not the destination allowlist.

Binding to the original origin (via[0]) rather than the immediately previous hop is load-bearing: net/http copies the initial request's headers into every redirect request before CheckRedirect runs (see makeHeadersCopier — custom headers such as X-Api-Key are copied unconditionally), so a chain like Prowlarr A -> external B -> B/path would otherwise reintroduce the key on the second hop (prev == req host) after it was stripped on the first. A hop that returns to the original origin is allowed to carry credentials again, since the key belongs to that host.

func ValidateDownloadURL

func ValidateDownloadURL(raw string) error

ValidateDownloadURL checks that a URL supplied by a remote indexer is safe to fetch. Indexer search responses drive these requests, so a compromised or hostile indexer would otherwise be able to point AltMount at loopback, link-local or private addresses — including cloud instance-metadata endpoints — turning the download path into an SSRF primitive.

Security contract: literal-IP blocking ONLY. A literal IP that is loopback, private, link-local (unicast or multicast) or unspecified is rejected, as are "localhost" names. DNS hostnames are NOT resolved here: a DNS name that resolves to a private address still passes. This check is not a destination allowlist. Callers re-validate every redirect hop with SafeDownloadCheckRedirect, which applies this same literal-IP-only rule per hop (DNS hostnames again NOT resolved). Credential stripping on cross-host redirects is a separate concern: it governs request headers, not the destination allowlist.

Types

type NetworkProxyConfig

type NetworkProxyConfig interface {
	GetHTTPProxy() string
	GetHTTPSProxy() string
	GetNoProxy() string
}

NetworkProxyConfig is the minimal interface the factory needs from the application config. Implemented by config.NetworkConfig — declared here to avoid an internal/config ↔ internal/httpclient import cycle.

type Option

type Option func(*Options)

Option is a functional option for configuring HTTP clients.

func WithProxyConfig

func WithProxyConfig(httpProxy, httpsProxy, noProxy string) Option

WithProxyConfig returns an Option that installs a proxy-aware *http.Transport derived from the supplied values. Pass empty strings to disable proxying.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the client timeout.

type Options

type Options struct {
	Timeout   time.Duration
	Transport *http.Transport
}

Options configures an HTTP client.

Jump to

Keyboard shortcuts

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