httpclient

package
v0.0.0-...-7e9ebae Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package httpclient provides a lightweight HTTP client with interface binding, proxy support, and precise timing metrics. It replaces curl CLI invocations for all runtime HTTP operations in the application.

Index

Constants

This section is empty.

Variables

View Source
var DefaultClient = New()

DefaultClient is the package-level client for convenient use.

Functions

func DialTCP

func DialTCP(ctx context.Context, iface, addr string, connectTimeout time.Duration) (net.Conn, error)

DialTCP opens a single TCP connection to addr ("host:port"), bound to iface via SO_BINDTODEVICE when non-empty. Hostnames resolve through the same iface-bound DNS path the HTTP client uses. The caller closes the conn.

func LookupAllIPv4ForBind

func LookupAllIPv4ForBind(ctx context.Context, host string, dnsServers []string, bindIface string) ([]string, error)

LookupAllIPv4ForBind resolves host to ALL of its IPv4 addresses. Server and bind semantics match LookupIPv4ForBind, but every A record found is returned (deduplicated) instead of just the first. Needed wherever every address of a host must be covered: a domain may serve several A records (CDN, round-robin) and the client can connect to any of them. Returns an error only when nothing could be resolved.

func LookupCNAMETargetsViaDNS

func LookupCNAMETargetsViaDNS(ctx context.Context, host, dnsServer, bindIface string) ([]string, error)

lookupAllAViaDNS is the multi-record sibling of lookupAViaDNS: it returns every A record in the response (following a single CNAME chain) rather than stopping at the first. LookupCNAMETargetsViaDNS returns CNAME target hostnames from the answer section for host (not followed). Useful for discovering CDN origin names that should be resolved into ipset entries.

func LookupIPv4ForBind

func LookupIPv4ForBind(ctx context.Context, host string, dnsServers []string, bindIface string) (string, error)

LookupIPv4ForBind resolves host to an IPv4 address. When dnsServers is non-empty, queries are sent over UDP bound to bindIface (tunnel DNS). Otherwise the system resolver is used (ip4 only).

func NewTransport

func NewTransport(cfg TransportConfig) (*http.Transport, error)

NewTransport returns an http.Transport with optional interface binding and/or HTTP proxy. Caller owns the returned value; clone per-client if needed.

func ParseTime

func ParseTime(s string) time.Time

ParseTime parses an HTTP Date header value. Returns zero time on failure.

func ResolveIPv4Resilient

func ResolveIPv4Resilient(ctx context.Context, host string, dnsServers []string, bindIface string) (string, error)

ResolveIPv4Resilient resolves host to IPv4 with a failure-tolerant chain: fresh lookup (tunnel DNS when dnsServers set, system resolver otherwise), then the cached last-known-good answer, then the system resolver as the last resort. A flaky resolver must not turn into a false probe failure — probing an hour-stale IP still measures the tunnel honestly. Entries are keyed by (bindIface, host): different tunnel exits may legitimately resolve one name to different IPs (geo-DNS). Stale entries live until process restart.

func SecToMs

func SecToMs(sec float64) int

SecToMs converts seconds (float64) to milliseconds (int) with the same floor-to-1ms rule used by the existing curl-based callers.

Types

type CallConfig

type CallConfig struct {
	// URL is the request target. Required.
	URL string

	// Interface binds the request to a kernel device (curl --interface).
	// Implemented via SO_BINDTODEVICE on the dialer.
	Interface string

	// DNSServers are used for hostname resolution when Interface is set.
	// Queries go over UDP bound to the same interface (tunnel DNS).
	DNSServers []string

	// ProxyURL routes through an HTTP/SOCKS proxy (curl -x / --proxy).
	// Supports "http://", "socks5://", "socks5h://" schemes.
	ProxyURL string

	// Method defaults to GET; set to "HEAD" for monitoring probes.
	Method string

	// MaxTime is the overall request timeout (curl --max-time).
	MaxTime time.Duration

	// ConnectTimeout is the TCP connect timeout (curl --connect-timeout).
	ConnectTimeout time.Duration

	// DiscardBody when true skips reading the response body (curl -o /dev/null).
	DiscardBody bool
}

CallConfig captures all the variation in how curl is invoked. Every field is optional — zero value means "not applicable".

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client wraps http.Client with interface-binding dialer. Safe for concurrent use after construction. Reuse the same Client instance; per-call state (interface, proxy) is isolated inside each Do call.

func New

func New() *Client

New creates a Client with sensible defaults.

func (*Client) Do

func (c *Client) Do(ctx context.Context, cfg CallConfig) (*Result, error)

Do executes an HTTP request per cfg and returns the result and metrics. Context cancellation and timeouts are respected.

type HTTPDoer

type HTTPDoer interface {
	Do(ctx context.Context, cfg CallConfig) (*Result, error)
}

HTTPDoer is the interface satisfied by Client for test stubs.

type Metrics

type Metrics struct {
	HTTPCode       int     // e.g. 204, 200, 404
	TimeNameLookup float64 // Cumulative: time from start to DNS done (seconds)
	TimeConnect    float64 // Cumulative: time from start to TCP connect done (seconds)
	TimeTotal      float64 // Cumulative: full request duration (seconds)
}

Metrics mirrors curl's -w output fields used across the codebase.

type Result

type Result struct {
	Body    string      // Response body (may be empty when discardBody is used)
	Headers http.Header // Response headers
	Metrics Metrics
}

Result is the unified return type for all operations.

type TransportConfig

type TransportConfig struct {
	// Interface binds outgoing sockets to a kernel device (SO_BINDTODEVICE).
	Interface string

	// ProxyURL routes through an HTTP proxy, e.g. "http://127.0.0.1:1080".
	ProxyURL string

	// DNSServers are used for hostname resolution when Interface is set.
	DNSServers []string
}

TransportConfig configures a reusable *http.Transport for http.Client.

Jump to

Keyboard shortcuts

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