cache

package
v0.0.0-...-476de0a Latest Latest
Warning

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

Go to latest
Published: May 13, 2026 License: GPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package cache implements a two-tier HTTP response cache for anzu-proxy.

The memory tier uses an LRU with a configurable byte budget. The optional disk tier shards entries across 256 directories by hash prefix, writes atomically, and persists across restarts. Hot disk hits are promoted back to memory. Both tiers evict by LRU.

On-disk format (one file per cached entry):

[4]   magic "ANZU"
[2]   format version (BE uint16)
[4]   status code (BE uint32)
[8]   expires_at unix seconds (BE int64)
[4]   header bytes length (BE uint32)
[N]   header bytes (JSON of http.Header)
[8]   body length (BE uint64)
[N]   body bytes
[32]  SHA-256 of everything above

The trailing checksum makes corrupted files detectable; bad files are silently dropped and the upstream is re-fetched.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BytesFlag

func BytesFlag(name string, defaultVal int64, usage string) *int64

bytesFlag is a convenience wrapper to register a bytesValue with the stdlib `flag` package, mirroring `flag.Int64`'s API.

func CacheKey

func CacheKey(method, rawURL string) string

CacheKey builds a canonical cache key from method + URL. When the disk tier is enabled, this string is SHA-256'd to form the on-disk filename — but in-memory we use the raw key for direct map lookup.

func DefaultCacheDir

func DefaultCacheDir() (string, string, error)

defaultCacheDir picks a sensible disk-cache location when the user enables the disk tier but doesn't pass -cache-dir explicitly.

The strategy mirrors how well-behaved Linux daemons choose paths:

  1. If we look like we're running as root in a snap, use $SNAP_COMMON.
  2. Otherwise, if running as root: /var/cache/anzu-proxy (FHS).
  3. Else if $XDG_CACHE_HOME is set: $XDG_CACHE_HOME/anzu-proxy.
  4. Else if $HOME is set: $HOME/.cache/anzu-proxy.
  5. Last resort: $TMPDIR/anzu-proxy-cache (with a warning — this loses cache data on /tmp cleanup).

The chosen path is mkdir'd and returned; an error is only returned if every fallback fails to create a writable directory.

func DrainAndCache

func DrainAndCache(cache *ResponseCache, key string, resp *http.Response, ttl time.Duration) io.ReadCloser

returns a fresh ReadCloser the caller may use to forward the body.

func IsCacheable

func IsCacheable(resp *http.Response) bool

IsCacheable reports whether an HTTP response may be stored, looking only at the response. Callers that have the originating request should use ShouldCacheExchange, which additionally refuses to cache responses to credentialed requests.

Method-level filtering (GET, HEAD, OPTIONS) is handled by isCacheableMethod at the call site in http_handler.go, keeping this function focused on response attributes only.

func IsCacheableMethod

func IsCacheableMethod(method string) bool

isCacheableMethod reports whether method is one whose responses may be stored in a shared cache (GET, HEAD, OPTIONS per RFC 7234 §3).

func ShouldCacheExchange

func ShouldCacheExchange(req *http.Request, resp *http.Response) bool

ShouldCacheExchange decides whether a (request, response) pair may be stored. It applies IsCacheable(resp) first and then refuses to store responses to credentialed requests (Authorization or Cookie present) unless the origin explicitly opted in with Cache-Control: public.

Background: with -htpasswd multi-user mode, the cache key is shared across users (sha256(method+url)). Without this guard, user A's authenticated GET would be served from cache to user B — a cross-user data leak. RFC 7234 §3.2 and §5.2.2.5 require the same behaviour for shared caches.

func TTLFromResponse

func TTLFromResponse(resp *http.Response, defaultTTL time.Duration) time.Duration

TTLFromResponse extracts the TTL: honours Cache-Control: s-maxage and max-age, falls back to defaultTTL.

Types

type CacheConfig

type CacheConfig struct {
	MaxMemoryBytes int64         // 0 = unlimited (still bounded by MaxEntries)
	MaxDiskBytes   int64         // 0 = no disk tier
	MaxObjectBytes int64         // 0 = unlimited per object
	MaxEntries     int           // hard cap on entry count across both tiers (0 = unlimited)
	DiskDir        string        // disk cache root; created if absent. Empty = no disk tier.
	TTL            time.Duration // default TTL when origin doesn't say
}

CacheConfig configures a ResponseCache.

type CacheEntry

type CacheEntry struct {
	StatusCode int
	Headers    http.Header
	Body       []byte
	ExpiresAt  time.Time
}

CacheEntry holds one cached HTTP response.

func (*CacheEntry) IsExpired

func (e *CacheEntry) IsExpired() bool

IsExpired reports whether this entry is past its TTL.

type CacheLocation

type CacheLocation int

CacheLocation tells us where an indexed entry currently lives.

type ResponseCache

type ResponseCache struct {

	// Default TTL when origin doesn't specify Cache-Control.
	TTL time.Duration
	// contains filtered or unexported fields
}

ResponseCache is the public type used by the HTTP handlers.

func NewResponseCache

func NewResponseCache(cfg CacheConfig) (*ResponseCache, error)

NewResponseCache creates a configured cache. If cfg.DiskDir is non-empty, it is created (mkdir -p) and any existing on-disk state is loaded into the index.

func (*ResponseCache) Close

func (c *ResponseCache) Close()

Close stops background workers. Safe to call multiple times.

func (*ResponseCache) Get

func (c *ResponseCache) Get(key string) *CacheEntry

Get retrieves an entry from either tier. A disk hit is promoted into the memory tier so subsequent hits are RAM-fast.

func (*ResponseCache) Set

func (c *ResponseCache) Set(key string, entry *CacheEntry)

Set inserts or replaces an entry. Objects larger than MaxObjectBytes are dropped silently — caller continues to forward the response uncached.

func (*ResponseCache) Stats

func (c *ResponseCache) Stats() (entries int, memBytes, diskBytes int64)

Stats returns counters useful for monitoring.

Jump to

Keyboard shortcuts

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