httpcc

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package httpcc parses and evaluates HTTP caching fields (RFC 9111): Cache-Control directives, lifetimes and entry evaluation (docs/04-lld.md §4).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CorrectedInitialAge

func CorrectedInitialAge(ageHdr string, reqTime, respTime time.Time) time.Duration

CorrectedInitialAge returns age_value + response_delay (RFC 9111 §4.2.3, FR-FRS-4). Date is deliberately not an input: apparent_age would compare the origin's clock with ours (T-30). A list-based Age uses its first member; an invalid one is ignored (RFC 9111 §5.1).

func CurrentAge

func CurrentAge(e *store.Entry, now time.Time) time.Duration

CurrentAge returns the entry's age at now (FR-FRS-4). Both times carry monotonic readings in process, so a wall-clock step cannot change it (FR-FRS-8). Negative intermediate ages clamp to zero (a decoded entry can carry any value); the sum saturates.

func Jitter

func Jitter(lt time.Duration, frac float64, minLT time.Duration, u float64) time.Duration

Jitter shortens lt by frac×u (u in [0, 1)) when lt is at least minLT (FR-FRS-5). It never lengthens a lifetime, even for out-of-range inputs.

func Lifetime

func Lifetime(d ResponseDirectives, h http.Header, status int, respTime time.Time, cfg Config) (lt time.Duration, heuristic bool)

Lifetime returns the freshness lifetime of a response received at respTime (FR-FRS-1 to FR-FRS-3) and whether it is heuristic. Origin dates are compared with each other; respTime stands in only when Date is absent or invalid (T-30).

func ParseDate

func ParseDate(s string) (time.Time, bool)

ParseDate parses an HTTP-date in any of the three RFC 9110 §5.6.7 forms. It is http.ParseTime without its zone laxity: the RFC 850 layout accepts any abbreviation and resolves it against the host's TZ (PST is -8h in Los Angeles and +0 elsewhere), so the same bytes would give a different lifetime per deployment. RFC 850 dates must end in GMT; the IMF-fixdate layout has GMT as a literal and asctime has no zone. ponytail: RFC 850 two-digit years use Go's 1969 pivot, not RFC 9110's 50-years-ahead rule, so 70-75 read as the 1970s. The form is obsolete and only the origin sends it. Parse the year by hand if that matters.

func StaleWindows

func StaleWindows(d ResponseDirectives, cfg Config) (swr, sie time.Duration)

StaleWindows returns the SWR and SIE windows a response permits (FR-STL-1 to FR-STL-3). Each operator default applies only when the origin sent neither its own directive nor s-maxage; an invalid origin value is 0.

Types

type Config

type Config struct {
	HeuristicFraction      float64
	HeuristicMax           time.Duration
	DefaultTTL             time.Duration
	DefaultSWR, DefaultSIE time.Duration
}

Config holds the freshness settings httpcc reads, with the engine's defaults already applied (weir.FreshnessConfig, 04 §1.1).

type RequestDirectives

type RequestDirectives struct {
	NoStore, NoCache, OnlyIfCached bool
	MaxAge, MinFresh, MaxStale     Seconds
}

RequestDirectives holds the request cache directives (RFC 9111 §5.2.1). NoCache is also set by Pragma: no-cache without Cache-Control. A max-stale without argument accepts any staleness and parses as the delta-seconds ceiling.

func ParseRequest

func ParseRequest(h http.Header) RequestDirectives

ParseRequest parses the Cache-Control lines of h, or its Pragma lines when it has no Cache-Control (RFC 9111 §5.4, FR-SRV-8). Repeated delta-seconds directives keep the first value; request directives are advisory (D5).

type ResponseDirectives

type ResponseDirectives struct {
	MaxAge, SMaxAge, SWR, SIE       Seconds
	NoStore, NoCache, Private       bool
	Public, MustRevalidate          bool
	ProxyRevalidate, MustUnderstand bool
	// Duplicates reports a delta-seconds directive (max-age, s-maxage,
	// stale-while-revalidate, stale-if-error) repeated with different values,
	// which makes the lifetime zero (FR-FRS-2).
	Duplicates bool
	// Malformed reports a field whose meaning had to be guessed: an unclosed
	// quoted string, or an argument on public or must-revalidate. The
	// guesses only restrict; storing a response to an Authorization request
	// needs a field without them (FR-STO-5, T-8).
	Malformed bool
}

ResponseDirectives holds the response Cache-Control directives Weir acts on (RFC 9111 §5.2.2). Qualified no-cache and private count as unqualified.

func ParseResponse

func ParseResponse(h http.Header) ResponseDirectives

ParseResponse parses every Cache-Control line of h. It never fails: unknown directives are ignored (RFC 9111 §5.2.3) and malformed arguments are recorded as Invalid.

func (*ResponseDirectives) Unusable

func (d *ResponseDirectives) Unusable() bool

Unusable reports an invalid or conflicting delta-seconds directive, which makes the lifetime zero (FR-FRS-2, RFC 9111 §4.2.1).

type Seconds

type Seconds struct {
	V       int64
	Set     bool
	Invalid bool
}

Seconds is a parsed delta-seconds argument. Set reports that the directive appeared; Invalid reports a missing, signed or non-digit argument, which makes the lifetime zero (FR-FRS-2). V is 0 when Invalid.

type State

type State uint8

State is what a stored response may be used for at lookup (04 §4.3).

const (
	Fresh           State = iota + 1 // serve as is
	StaleSWR                         // serve stale and refresh in the background (FR-STL-1)
	NeedsValidation                  // revalidate in the foreground before serving
	Unusable                         // treat as a miss (FR-PRG-3)
)

State values. The zero State is invalid, so a forgotten assignment never reads as Fresh.

func Evaluate

func Evaluate(e *store.Entry, ep store.Epoch, epOK bool, now time.Time) (st State, staleness time.Duration, sieOK bool)

Evaluate classifies e at now. ep is the newest epoch that applies to e; the caller has already matched it against e.RequestTime (FR-PRG-7), and epOK is false when none applies. staleness is negative while fresh; for hard-purged and invalidated entries it ignores the epoch. sieOK reports whether stale-if-error may serve e (FR-STL-2); it is false for Fresh and Unusable.

Jump to

Keyboard shortcuts

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