httpx

package
v2.0.1 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package httpx is WaxTap's internal HTTP client wrapper. It adds retry, exponential backoff, rate-limit handling, and an optional per-host limiter on top of an injected *http.Client.

Design notes:

  • No global timeout is imposed here. Callers set per-operation deadlines on request contexts, so a long legitimate download is not killed by an unrelated global cap while a hung socket still cannot leak a goroutine.
  • Retry-After is honored but capped by MaxRetryWait: YouTube can demand hours on an IP ban, so beyond the cap we fail fast with *waxerr.RateLimitError instead of sleeping a worker.
  • Retried requests must be replayable: a request with a body but no GetBody is attempted exactly once.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Sleep

func Sleep(ctx context.Context, d time.Duration) error

Sleep waits for d or until ctx is done, whichever comes first, returning the context error on cancellation. A non-positive d returns immediately.

func WithThrottleHook

func WithThrottleHook(ctx context.Context, h ThrottleHook) context.Context

WithThrottleHook returns a context that reports throttle events to h. A nil hook clears an inherited hook.

Types

type Client

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

Client performs HTTP requests with retry, backoff, and rate-limit handling.

func New

func New(cfg Config) *Client

New returns a Client, filling unset Config fields with defaults.

func (*Client) Do

func (c *Client) Do(req *http.Request) (*http.Response, error)

Do executes req with retry/backoff and rate-limit handling. The request context governs cancellation and per-operation deadlines; a context error is never retried. On a capped-out Retry-After it returns *waxerr.RateLimitError.

On success the caller owns the returned response body. On retried or rate-limited responses the intermediate bodies are drained and closed here.

func (*Client) Jar

func (c *Client) Jar() http.CookieJar

Jar returns the cookie jar of the underlying *http.Client, or nil if it has none. Higher layers use this to decide whether a cookie-dependent session bootstrap is worthwhile (and where to seed cookies).

type Config

type Config struct {
	// HTTPClient is the underlying client. It should set a DialContext and a
	// conservative Timeout (or rely on per-request context deadlines). If nil,
	// http.DefaultClient is used.
	HTTPClient *http.Client
	// Logger receives debug logs for retries/backoff. If nil, logs are discarded.
	Logger *slog.Logger
	// Limiter gates requests per host. If nil, no limiting is applied.
	Limiter Limiter

	// MaxRetries is the number of additional attempts after the first.
	MaxRetries int
	// BaseBackoff is the base of the exponential backoff schedule.
	BaseBackoff time.Duration
	// MaxBackoff caps a single backoff sleep.
	MaxBackoff time.Duration
	// MaxRetryWait caps an honored Retry-After. Beyond it, Do fails fast with
	// *waxerr.RateLimitError rather than sleeping.
	MaxRetryWait time.Duration

	// Cooldown is the minimum host penalty after a rate-limit response. A longer
	// Retry-After value takes precedence, up to MaxRetryWait. Zero disables the
	// base cooldown.
	Cooldown time.Duration
}

Config configures a Client. The zero value is usable; New fills sane defaults.

type HostLimiter

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

HostLimiter spaces requests and applies cooldowns independently per host.

Requests are admitted at most once every 1/qps seconds; bursts are not allowed. HostLimiter.Penalize pauses a host even when qps is non-positive.

func NewHostLimiter

func NewHostLimiter(qps float64) *HostLimiter

NewHostLimiter returns a per-host limiter that admits qps requests per second. A non-positive qps disables spacing but still permits cooldowns.

func (*HostLimiter) Penalize

func (l *HostLimiter) Penalize(host string, d time.Duration)

Penalize pauses requests to host for at least d. It also moves the spacing schedule forward so requests remain spaced after the cooldown. A non-positive duration has no effect.

func (*HostLimiter) Wait

func (l *HostLimiter) Wait(ctx context.Context, host string) error

Wait blocks until a request to host may proceed or ctx is done.

Wait rechecks the host cooldown after each timer wakeup. On cancellation, it rolls back the request's spacing reservation when no later request depends on it.

type Limiter

type Limiter interface {
	// Wait blocks until host may receive another request or ctx is canceled.
	Wait(ctx context.Context, host string) error
	// Penalize pauses requests to host for at least d.
	Penalize(host string, d time.Duration)
}

Limiter gates outbound requests. Wait blocks until a request may proceed or ctx is done. Penalize pauses requests to one host for at least d.

type NopLimiter

type NopLimiter struct{}

NopLimiter performs no rate limiting.

func (NopLimiter) Penalize

func (NopLimiter) Penalize(string, time.Duration)

Penalize implements Limiter.

func (NopLimiter) Wait

Wait implements Limiter.

type ThrottleEvent

type ThrottleEvent struct {
	Host       string        // request host
	StatusCode int           // rate-limit response status
	RetryAfter time.Duration // parsed Retry-After; zero if missing or invalid
	Penalty    time.Duration // duration passed to Limiter.Penalize
	Phase      ThrottlePhase // point in the throttle lifecycle
}

ThrottleEvent describes rate limiting by one host.

type ThrottleHook

type ThrottleHook func(ThrottleEvent)

ThrottleHook receives throttle events. It may be called from parallel request workers, so it must be safe for concurrent use.

type ThrottlePhase

type ThrottlePhase int

ThrottlePhase identifies when a throttle event occurred.

const (
	// ThrottleDetected is reported after a rate-limit response is received and
	// the host is penalized.
	ThrottleDetected ThrottlePhase = iota
	// ThrottleRetryStarted is reported when a retry begins after backoff.
	ThrottleRetryStarted
)

Jump to

Keyboard shortcuts

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