cache

package
v0.0.0-...-1f1918b Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package cache provides HTTP caching functionality for the Bifrost proxy. It supports tiered storage (memory + disk), domain-based caching rules, and is inspired by steamcache/lancache for game download caching.

Index

Constants

View Source
const EvictionReasonLRU = "lru"

EvictionReasonLRU is used when evicting due to LRU policy.

View Source
const EvictionReasonSize = "size"

EvictionReasonSize is used when evicting due to size limit.

View Source
const EvictionReasonTTL = "ttl"

EvictionReasonTTL is used when evicting due to TTL expiry.

View Source
const MissReasonDisabled = "disabled"

MissReasonDisabled is used when caching is disabled.

View Source
const MissReasonExpired = "expired"

MissReasonExpired is used when the entry has expired.

View Source
const MissReasonNoRule = "no_rule"

MissReasonNoRule is used when no caching rule matches.

View Source
const MissReasonNotFound = "not_found"

MissReasonNotFound is used when the entry is not in cache.

Variables

View Source
var (
	// ErrNotFound indicates the requested entry was not found in cache.
	ErrNotFound = errors.New("cache entry not found")

	// ErrStorageFull indicates the storage has reached its capacity limit.
	ErrStorageFull = errors.New("cache storage full")

	// ErrEntrySizeExceeded indicates the entry exceeds the maximum allowed size.
	ErrEntrySizeExceeded = errors.New("entry size exceeds maximum")

	// ErrInvalidKey indicates the cache key is invalid.
	ErrInvalidKey = errors.New("invalid cache key")

	// ErrStorageClosed indicates the storage has been closed.
	ErrStorageClosed = errors.New("storage is closed")
)

Common errors for storage operations.

Functions

func AllPresets

func AllPresets() map[PresetName]Preset

AllPresets returns all available presets as a map.

func GenerateSimpleKey

func GenerateSimpleKey(method, host, path string) string

GenerateSimpleKey creates a simple cache key from method, host, and path. This is a convenience function for quick lookups.

func KeyPrefix

func KeyPrefix(key string, n int) string

KeyPrefix returns the first n characters of a key for sharding. Used for organizing files in subdirectories on disk.

Types

type ByteRange

type ByteRange struct {
	Start int64
	End   int64
}

ByteRange represents a single byte range.

func CoalesceRanges

func CoalesceRanges(ranges []ByteRange) []ByteRange

CoalesceRanges merges overlapping or adjacent ranges.

func (ByteRange) ContentRange

func (r ByteRange) ContentRange(total int64) string

ContentRange returns the Content-Range header value for this range.

func (ByteRange) Length

func (r ByteRange) Length() int64

Length returns the number of bytes in this range.

type ByteSize

type ByteSize int64

ByteSize is a size in bytes that can be unmarshaled from human-readable strings.

const (
	KB ByteSize = 1 << (10 * iota)
	MB
	GB
	TB
	PB
)

func (ByteSize) Int64

func (b ByteSize) Int64() int64

func (ByteSize) MarshalJSON

func (b ByteSize) MarshalJSON() ([]byte, error)

func (ByteSize) MarshalYAML

func (b ByteSize) MarshalYAML() (interface{}, error)

func (ByteSize) String

func (b ByteSize) String() string

func (*ByteSize) UnmarshalJSON

func (b *ByteSize) UnmarshalJSON(data []byte) error

func (*ByteSize) UnmarshalYAML

func (b *ByteSize) UnmarshalYAML(value *yaml.Node) error

type BytesReadCloser

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

BytesReadCloser wraps a byte slice as an io.ReadCloser.

func NewBytesReadCloser

func NewBytesReadCloser(data []byte) *BytesReadCloser

NewBytesReadCloser creates a new bytes reader.

func (*BytesReadCloser) Close

func (br *BytesReadCloser) Close() error

Close implements io.Closer.

func (*BytesReadCloser) Read

func (br *BytesReadCloser) Read(p []byte) (n int, err error)

Read implements io.Reader.

func (*BytesReadCloser) Seek

func (br *BytesReadCloser) Seek(offset int64, whence int) (int64, error)

Seek implements io.Seeker.

type CacheControl

type CacheControl struct {
	// MaxAge specifies the maximum age in seconds.
	MaxAge int `json:"max_age,omitempty"`

	// SMaxAge specifies the shared cache maximum age.
	SMaxAge int `json:"s_maxage,omitempty"`

	// NoCache indicates the response must be revalidated.
	NoCache bool `json:"no_cache,omitempty"`

	// NoStore indicates the response must not be stored.
	NoStore bool `json:"no_store,omitempty"`

	// MustRevalidate indicates stale responses must be revalidated.
	MustRevalidate bool `json:"must_revalidate,omitempty"`

	// Public indicates the response may be cached by any cache.
	Public bool `json:"public,omitempty"`

	// Private indicates the response is for a single user.
	Private bool `json:"private,omitempty"`

	// Immutable indicates the response will not change.
	Immutable bool `json:"immutable,omitempty"`
}

CacheControl represents parsed Cache-Control header directives.

func ParseCacheControl

func ParseCacheControl(header string) *CacheControl

ParseCacheControl parses a Cache-Control header value.

type CacheStats

type CacheStats struct {
	Enabled          bool    `json:"enabled"`
	StorageType      string  `json:"storage_type"`
	Entries          int64   `json:"entries"`
	TotalSize        int64   `json:"total_size_bytes"`
	MaxSize          int64   `json:"max_size_bytes"`
	UsedPercent      float64 `json:"used_percent"`
	HitCount         int64   `json:"hit_count"`
	MissCount        int64   `json:"miss_count"`
	HitRate          float64 `json:"hit_rate"`
	EvictionCount    int64   `json:"eviction_count"`
	RulesCount       int     `json:"rules_count"`
	PresetsCount     int     `json:"presets_count"`
	CustomRulesCount int     `json:"custom_rules_count"`
}

CacheStats holds overall cache statistics.

type Config

type Config struct {
	// Enabled enables or disables caching.
	Enabled bool `yaml:"enabled" json:"enabled"`

	// DefaultTTL is the default time-to-live for cached entries.
	DefaultTTL Duration `yaml:"default_ttl" json:"default_ttl"`

	// MaxFileSize is the maximum size of a single cached file.
	MaxFileSize ByteSize `yaml:"max_file_size" json:"max_file_size"`

	// Storage configures the storage backend.
	Storage StorageConfig `yaml:"storage" json:"storage"`

	// Presets are built-in cache rules for common CDNs.
	Presets []string `yaml:"presets,omitempty" json:"presets,omitempty"`

	// Rules are custom caching rules.
	Rules []RuleConfig `yaml:"rules,omitempty" json:"rules,omitempty"`
}

Config contains all cache configuration settings.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a cache configuration with sensible defaults.

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the cache configuration.

type DiskConfig

type DiskConfig struct {
	// Path is the directory for storing cached files.
	Path string `yaml:"path" json:"path"`

	// MaxSize is the maximum total size of the disk cache.
	MaxSize ByteSize `yaml:"max_size" json:"max_size"`

	// CleanupInterval is how often to run cleanup of expired entries.
	CleanupInterval Duration `yaml:"cleanup_interval" json:"cleanup_interval"`

	// ShardCount is the number of subdirectories for sharding (default: 256).
	ShardCount int `yaml:"shard_count,omitempty" json:"shard_count,omitempty"`
}

DiskConfig configures disk storage.

type DiskStorage

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

DiskStorage stores cache entries on disk.

func NewDiskStorage

func NewDiskStorage(cfg *DiskConfig) (*DiskStorage, error)

NewDiskStorage creates a new disk storage.

func (*DiskStorage) Clear

func (d *DiskStorage) Clear(ctx context.Context) error

Clear removes all entries from the storage.

func (*DiskStorage) Delete

func (d *DiskStorage) Delete(ctx context.Context, key string) error

Delete removes a cache entry by key.

func (*DiskStorage) Exists

func (d *DiskStorage) Exists(ctx context.Context, key string) bool

Exists checks if a key exists in the cache.

func (*DiskStorage) Get

func (d *DiskStorage) Get(ctx context.Context, key string) (*Entry, error)

Get retrieves a cache entry by key.

func (*DiskStorage) GetMetadata

func (d *DiskStorage) GetMetadata(ctx context.Context, key string) (*Metadata, error)

GetMetadata returns only the metadata for a key.

func (*DiskStorage) GetRange

func (d *DiskStorage) GetRange(ctx context.Context, key string, start, end int64) (io.ReadCloser, error)

GetRange retrieves a byte range from a cached entry.

func (*DiskStorage) List

func (d *DiskStorage) List(ctx context.Context, domain string, offset, limit int) ([]*Metadata, int64, error)

List returns all metadata entries.

func (*DiskStorage) Put

func (d *DiskStorage) Put(ctx context.Context, key string, entry *Entry) error

Put stores a cache entry.

func (*DiskStorage) Start

func (d *DiskStorage) Start(ctx context.Context) error

Start initializes the storage backend.

func (*DiskStorage) Stats

func (d *DiskStorage) Stats() StorageStats

Stats returns storage statistics.

func (*DiskStorage) Stop

func (d *DiskStorage) Stop(ctx context.Context) error

Stop gracefully shuts down the storage backend.

type Duration

type Duration time.Duration

Duration is a time.Duration that can be unmarshaled from YAML/JSON strings.

func (Duration) Duration

func (d Duration) Duration() time.Duration

func (Duration) MarshalJSON

func (d Duration) MarshalJSON() ([]byte, error)

func (Duration) MarshalYAML

func (d Duration) MarshalYAML() (interface{}, error)

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(b []byte) error

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(value *yaml.Node) error

type Entry

type Entry struct {
	// Metadata contains cache entry metadata.
	Metadata *Metadata

	// Body is the response body. For streaming large files, this is a reader
	// that streams from storage rather than loading into memory.
	Body io.ReadCloser
}

Entry represents a cached HTTP response.

func (*Entry) Close

func (e *Entry) Close() error

Close closes the entry's body if it exists.

type EvictionPolicy

type EvictionPolicy string

EvictionPolicy defines how entries are evicted when storage is full.

const (
	// EvictionLRU evicts least recently used entries.
	EvictionLRU EvictionPolicy = "lru"

	// EvictionLFU evicts least frequently used entries.
	EvictionLFU EvictionPolicy = "lfu"

	// EvictionFIFO evicts oldest entries first.
	EvictionFIFO EvictionPolicy = "fifo"
)

type Interceptor

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

Interceptor intercepts HTTP requests for caching.

func NewInterceptor

func NewInterceptor(manager *Manager) *Interceptor

NewInterceptor creates a new cache interceptor.

func (*Interceptor) HandleRequest

func (i *Interceptor) HandleRequest(ctx context.Context, conn net.Conn, req *http.Request) (bool, error)

HandleRequest attempts to serve a request from cache. Returns true if the request was handled (served from cache), false if it should be forwarded to the backend.

func (*Interceptor) NewResponseWriter

func (i *Interceptor) NewResponseWriter(conn net.Conn, req *http.Request) *ResponseWriter

NewResponseWriter creates a new response writer for interception.

func (*Interceptor) StoreResponse

func (i *Interceptor) StoreResponse(ctx context.Context, req *http.Request, resp *http.Response) (io.ReadCloser, error)

StoreResponse stores an HTTP response in the cache. The body is read and stored, and a new reader is returned for forwarding.

type KeyGenerator

type KeyGenerator struct {
	// IgnoreQuery ignores query string in key generation (useful for CDNs).
	IgnoreQuery bool

	// IgnoreScheme ignores the scheme (http/https) in key generation.
	IgnoreScheme bool

	// SortQueryParams sorts query parameters for consistent keys.
	SortQueryParams bool

	// IncludeHeaders includes specific headers in key generation (for Vary support).
	IncludeHeaders []string
}

KeyGenerator generates cache keys from HTTP requests.

func DefaultKeyGenerator

func DefaultKeyGenerator() *KeyGenerator

DefaultKeyGenerator returns a key generator with sensible defaults.

func (*KeyGenerator) GenerateKey

func (kg *KeyGenerator) GenerateKey(req *http.Request) string

GenerateKey creates a cache key from an HTTP request. The key is a SHA256 hash of the relevant request components.

func (*KeyGenerator) GenerateKeyFromURL

func (kg *KeyGenerator) GenerateKeyFromURL(method, urlStr string) (string, error)

GenerateKeyFromURL creates a cache key from a URL string. Useful for lookups when you don't have the full request.

type LimitedReadCloser

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

LimitedReadCloser wraps an io.ReadCloser with a size limit.

func NewLimitedReadCloser

func NewLimitedReadCloser(rc io.ReadCloser, limit int64) *LimitedReadCloser

NewLimitedReadCloser creates a new limited reader.

func (*LimitedReadCloser) Close

func (lrc *LimitedReadCloser) Close() error

Close implements io.Closer.

func (*LimitedReadCloser) Read

func (lrc *LimitedReadCloser) Read(p []byte) (n int, err error)

Read implements io.Reader with size limiting.

type Manager

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

Manager coordinates caching operations.

func NewManager

func NewManager(cfg *Config) (*Manager, error)

NewManager creates a new cache manager.

func (*Manager) Clear

func (m *Manager) Clear(ctx context.Context) error

Clear removes all entries from the cache.

func (*Manager) Delete

func (m *Manager) Delete(ctx context.Context, key string) error

Delete removes an entry from the cache.

func (*Manager) Get

func (m *Manager) Get(ctx context.Context, req *http.Request) (*Entry, error)

Get retrieves a cached response for a request. Returns nil if not found or expired.

func (*Manager) GetKeyGenerator

func (m *Manager) GetKeyGenerator() *KeyGenerator

GetKeyGenerator returns the key generator.

func (*Manager) IsEnabled

func (m *Manager) IsEnabled() bool

IsEnabled returns whether caching is enabled.

func (*Manager) KeyFor

func (m *Manager) KeyFor(req *http.Request) string

KeyFor generates a cache key for a request.

func (*Manager) Put

func (m *Manager) Put(ctx context.Context, req *http.Request, resp *http.Response, body io.ReadCloser) error

Put stores a response in the cache.

func (*Manager) Reload

func (m *Manager) Reload(cfg *Config) error

Reload hot-reloads cache rules from config.

func (*Manager) Rules

func (m *Manager) Rules() *RuleSet

Rules returns the rule set.

func (*Manager) ShouldCache

func (m *Manager) ShouldCache(req *http.Request) bool

ShouldCache checks if a request should be cached.

func (*Manager) Start

func (m *Manager) Start(ctx context.Context) error

Start starts the cache manager.

func (*Manager) Stats

func (m *Manager) Stats() CacheStats

Stats returns cache statistics.

func (*Manager) Stop

func (m *Manager) Stop(ctx context.Context) error

Stop stops the cache manager.

func (*Manager) Storage

func (m *Manager) Storage() Storage

Storage returns the storage backend (for advanced operations).

type MemoryConfig

type MemoryConfig struct {
	// MaxSize is the maximum total size of the memory cache.
	MaxSize ByteSize `yaml:"max_size" json:"max_size"`

	// MaxEntries is the maximum number of entries in memory.
	MaxEntries int `yaml:"max_entries" json:"max_entries"`

	// EvictPolicy is the eviction policy: lru, lfu, or fifo.
	EvictPolicy string `yaml:"evict_policy" json:"evict_policy"`
}

MemoryConfig configures in-memory storage.

type MemoryStorage

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

MemoryStorage is an in-memory cache storage with LRU eviction.

func NewMemoryStorage

func NewMemoryStorage(cfg *MemoryConfig) *MemoryStorage

NewMemoryStorage creates a new in-memory storage.

func (*MemoryStorage) CleanupExpired

func (m *MemoryStorage) CleanupExpired() int

CleanupExpired removes all expired entries.

func (*MemoryStorage) Clear

func (m *MemoryStorage) Clear(ctx context.Context) error

Clear removes all entries from the storage.

func (*MemoryStorage) DataForKey

func (m *MemoryStorage) DataForKey(key string) ([]byte, bool)

DataForKey returns a copy of the raw data for a key (for testing).

func (*MemoryStorage) Delete

func (m *MemoryStorage) Delete(ctx context.Context, key string) error

Delete removes a cache entry by key.

func (*MemoryStorage) Exists

func (m *MemoryStorage) Exists(ctx context.Context, key string) bool

Exists checks if a key exists in the cache.

func (*MemoryStorage) Get

func (m *MemoryStorage) Get(ctx context.Context, key string) (*Entry, error)

Get retrieves a cache entry by key.

func (*MemoryStorage) GetMetadata

func (m *MemoryStorage) GetMetadata(ctx context.Context, key string) (*Metadata, error)

GetMetadata returns only the metadata for a key.

func (*MemoryStorage) GetRange

func (m *MemoryStorage) GetRange(ctx context.Context, key string, start, end int64) (io.ReadCloser, error)

GetRange retrieves a byte range from a cached entry.

func (*MemoryStorage) List

func (m *MemoryStorage) List(ctx context.Context, domain string, offset, limit int) ([]*Metadata, int64, error)

List returns all metadata entries.

func (*MemoryStorage) Put

func (m *MemoryStorage) Put(ctx context.Context, key string, entry *Entry) error

Put stores a cache entry.

func (*MemoryStorage) Start

func (m *MemoryStorage) Start(ctx context.Context) error

Start initializes the storage backend.

func (*MemoryStorage) Stats

func (m *MemoryStorage) Stats() StorageStats

Stats returns storage statistics.

func (*MemoryStorage) Stop

func (m *MemoryStorage) Stop(ctx context.Context) error

Stop gracefully shuts down the storage backend.

type Metadata

type Metadata struct {
	// Key is the unique cache key (SHA256 hash).
	Key string `json:"key"`

	// URL is the original request URL.
	URL string `json:"url"`

	// Host is the request host.
	Host string `json:"host"`

	// Method is the HTTP method (typically GET).
	Method string `json:"method"`

	// StatusCode is the HTTP response status code.
	StatusCode int `json:"status_code"`

	// Headers are the response headers to preserve.
	Headers http.Header `json:"headers"`

	// ContentLength is the total content length in bytes.
	ContentLength int64 `json:"content_length"`

	// ContentType is the MIME type of the content.
	ContentType string `json:"content_type"`

	// ETag is the entity tag for cache validation.
	ETag string `json:"etag,omitempty"`

	// LastModified is the last modification time from the origin.
	LastModified time.Time `json:"last_modified,omitempty"`

	// CacheControl contains parsed Cache-Control directives.
	CacheControl *CacheControl `json:"cache_control,omitempty"`

	// CreatedAt is when the entry was cached.
	CreatedAt time.Time `json:"created_at"`

	// ExpiresAt is when the entry should be considered stale.
	ExpiresAt time.Time `json:"expires_at"`

	// AccessedAt is the last access time (for LRU eviction).
	AccessedAt time.Time `json:"accessed_at"`

	// AccessCount is the number of times this entry was served.
	AccessCount int64 `json:"access_count"`

	// Size is the actual stored size in bytes.
	Size int64 `json:"size_bytes"`

	// Tier indicates which storage tier holds this entry (memory/disk).
	Tier string `json:"tier"`
}

Metadata holds cache entry metadata.

func (*Metadata) IsCacheable

func (m *Metadata) IsCacheable() bool

IsCacheable checks if the metadata indicates a cacheable response.

func (*Metadata) IsExpired

func (m *Metadata) IsExpired() bool

IsExpired checks if the entry has expired.

func (*Metadata) IsFresh

func (m *Metadata) IsFresh() bool

IsFresh checks if the entry is still fresh (not expired).

func (*Metadata) UpdateAccess

func (m *Metadata) UpdateAccess()

UpdateAccess updates the access time and count.

type Metrics

type Metrics struct {
	// Hits tracks cache hits by domain.
	Hits *prometheus.CounterVec

	// Misses tracks cache misses by domain and reason.
	Misses *prometheus.CounterVec

	// BytesServed tracks bytes served from cache vs origin.
	BytesServed *prometheus.CounterVec

	// BytesCached tracks total bytes stored in cache.
	BytesCached prometheus.Counter

	// StorageSize tracks current storage size by tier.
	StorageSize *prometheus.GaugeVec

	// StorageEntries tracks current entry count by tier.
	StorageEntries *prometheus.GaugeVec

	// StorageUsage tracks storage usage percentage by tier.
	StorageUsage *prometheus.GaugeVec

	// Evictions tracks evictions by tier and reason.
	Evictions *prometheus.CounterVec

	// OperationLatency tracks latency of cache operations.
	OperationLatency *prometheus.HistogramVec

	// ActiveRules tracks number of active cache rules.
	ActiveRules prometheus.Gauge

	// ActivePresets tracks number of enabled presets.
	ActivePresets prometheus.Gauge
}

Metrics holds Prometheus metrics for the cache.

func NewMetrics

func NewMetrics(registry prometheus.Registerer) *Metrics

NewMetrics creates a new Metrics instance and registers with the registry.

func (*Metrics) ObserveOperation

func (m *Metrics) ObserveOperation(operation string, seconds float64)

ObserveOperation records the latency of a cache operation.

func (*Metrics) RecordCachedBytes

func (m *Metrics) RecordCachedBytes(bytes int64)

RecordCachedBytes records bytes stored in cache.

func (*Metrics) RecordEviction

func (m *Metrics) RecordEviction(tier, reason string)

RecordEviction records a cache eviction.

func (*Metrics) RecordHit

func (m *Metrics) RecordHit(domain string, bytes int64)

RecordHit records a cache hit.

func (*Metrics) RecordMiss

func (m *Metrics) RecordMiss(domain, reason string)

RecordMiss records a cache miss.

func (*Metrics) RecordOriginBytes

func (m *Metrics) RecordOriginBytes(bytes int64)

RecordOriginBytes records bytes served from origin.

func (*Metrics) UpdateRuleMetrics

func (m *Metrics) UpdateRuleMetrics(rules, presets int)

UpdateRuleMetrics updates rule-related gauges.

func (*Metrics) UpdateStorageMetrics

func (m *Metrics) UpdateStorageMetrics(tier string, entries, size, maxSize int64)

UpdateStorageMetrics updates storage gauges.

type MultipartRangeWriter

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

MultipartRangeWriter writes multiple ranges as multipart MIME.

func NewMultipartRangeWriter

func NewMultipartRangeWriter(w io.Writer, contentType string, size int64) *MultipartRangeWriter

NewMultipartRangeWriter creates a writer for multipart range responses.

func (*MultipartRangeWriter) Boundary

func (w *MultipartRangeWriter) Boundary() string

Boundary returns the MIME boundary string.

func (*MultipartRangeWriter) Close

func (w *MultipartRangeWriter) Close() error

Close finishes the multipart message.

func (*MultipartRangeWriter) ContentType

func (w *MultipartRangeWriter) ContentType() string

ContentType returns the full Content-Type header value.

func (*MultipartRangeWriter) WritePart

func (w *MultipartRangeWriter) WritePart(r ByteRange, data []byte) error

WritePart writes a single range part.

type NopCloser

type NopCloser struct {
	io.Reader
}

NopCloser wraps an io.Reader to add a no-op Close method.

func (NopCloser) Close

func (NopCloser) Close() error

Close implements io.Closer.

type Preset

type Preset struct {
	Name        PresetName
	Description string
	Domains     []string
	TTL         time.Duration
	Priority    int
}

Preset defines a built-in cache rule preset.

func GetPreset

func GetPreset(name PresetName) (Preset, bool)

GetPreset returns a preset by name.

func GetPresetByString

func GetPresetByString(name string) (Preset, bool)

GetPresetByString returns a preset by string name.

type PresetInfo

type PresetInfo struct {
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Domains     []string `json:"domains"`
	TTL         string   `json:"ttl"`
	Priority    int      `json:"priority"`
}

PresetInfo provides information about a preset for API responses.

func AllPresetInfo

func AllPresetInfo() []*PresetInfo

AllPresetInfo returns information about all presets.

func GetPresetInfo

func GetPresetInfo(name PresetName) *PresetInfo

GetPresetInfo returns preset information.

type PresetName

type PresetName string

PresetName is the identifier for a built-in cache preset.

const (
	PresetSteam       PresetName = "steam"
	PresetOrigin      PresetName = "origin"
	PresetEpic        PresetName = "epic"
	PresetBattleNet   PresetName = "battlenet"
	PresetWindows     PresetName = "windows"
	PresetPlayStation PresetName = "playstation"
	PresetXbox        PresetName = "xbox"
	PresetNintendo    PresetName = "nintendo"
	PresetUbisoft     PresetName = "ubisoft"
	PresetRiot        PresetName = "riot"
	PresetApple       PresetName = "apple"
	PresetGoogle      PresetName = "google"
	PresetLinux       PresetName = "linux"
)

func PresetNames

func PresetNames() []PresetName

PresetNames returns the names of all available presets.

type RangeReader

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

RangeReader wraps a ReadSeeker to read a specific byte range.

func NewRangeReader

func NewRangeReader(reader io.ReadSeeker, start, end int64) (*RangeReader, error)

NewRangeReader creates a reader for a specific byte range.

func (*RangeReader) Read

func (r *RangeReader) Read(p []byte) (n int, err error)

Read implements io.Reader.

type RangeSpec

type RangeSpec struct {
	Ranges []ByteRange
}

RangeSpec represents a parsed Range request specification.

func ParseRangeSpec

func ParseRangeSpec(header string, size int64) (*RangeSpec, error)

ParseRangeSpec parses an HTTP Range header. Returns nil if the header is empty or invalid.

func (*RangeSpec) IsSatisfiable

func (rs *RangeSpec) IsSatisfiable(size int64) bool

IsSatisfiable checks if any of the ranges are satisfiable.

func (*RangeSpec) IsSingleRange

func (rs *RangeSpec) IsSingleRange() bool

IsSingleRange returns true if there's exactly one range.

func (*RangeSpec) TotalLength

func (rs *RangeSpec) TotalLength() int64

TotalLength returns the total number of bytes covered by all ranges.

type ResponseWriter

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

ResponseWriter wraps a connection for response interception.

func (*ResponseWriter) Flush

func (rw *ResponseWriter) Flush(ctx context.Context) error

Flush sends the buffered response to the connection and caches if appropriate.

func (*ResponseWriter) Header

func (rw *ResponseWriter) Header() http.Header

Header returns the response headers.

func (*ResponseWriter) Write

func (rw *ResponseWriter) Write(data []byte) (int, error)

Write writes body data.

func (*ResponseWriter) WriteHeader

func (rw *ResponseWriter) WriteHeader(statusCode int)

WriteHeader writes the status code.

type Rule

type Rule struct {
	// Name is the unique identifier for this rule.
	Name string

	// Domains are the original domain patterns (for API display).
	Domains []string

	// Matcher matches domains against this rule's patterns.
	Matcher *matcher.Matcher

	// Enabled indicates if this rule is active.
	Enabled bool

	// TTL is the time-to-live for cached entries.
	TTL time.Duration

	// MaxSize is the maximum file size to cache (0 = unlimited).
	MaxSize int64

	// Priority determines which rule applies when multiple match.
	// Higher priority rules take precedence.
	Priority int

	// Methods are HTTP methods to cache (empty = GET only).
	Methods []string

	// ContentTypes are MIME types to cache (empty = all).
	ContentTypes []string

	// IgnoreQuery ignores query string in cache key.
	IgnoreQuery bool

	// RespectCacheControl honors Cache-Control headers from origin.
	RespectCacheControl bool

	// StripHeaders are headers to remove before caching.
	StripHeaders []string

	// Preset is the preset name if this rule was created from a preset.
	Preset string
}

Rule defines caching behavior for matching domains.

func LoadPresets

func LoadPresets(names []string) []*Rule

LoadPresets loads rules from a list of preset names.

func NewRuleFromConfig

func NewRuleFromConfig(cfg RuleConfig) (*Rule, error)

NewRuleFromConfig creates a Rule from a RuleConfig.

func PresetToRule

func PresetToRule(preset Preset) *Rule

PresetToRule converts a preset to a Rule.

func (*Rule) MatchesContentType

func (r *Rule) MatchesContentType(contentType string) bool

MatchesContentType checks if the rule matches the content type.

func (*Rule) MatchesMethod

func (r *Rule) MatchesMethod(method string) bool

MatchesMethod checks if the rule matches the HTTP method.

func (*Rule) ShouldStripHeader

func (r *Rule) ShouldStripHeader(header string) bool

ShouldStripHeader checks if a header should be stripped before caching.

type RuleConfig

type RuleConfig struct {
	// Name is the unique name for this rule.
	Name string `yaml:"name" json:"name"`

	// Domains are the domain patterns to match.
	Domains []string `yaml:"domains" json:"domains"`

	// Enabled enables or disables this rule.
	Enabled bool `yaml:"enabled" json:"enabled"`

	// TTL is the time-to-live for entries matching this rule.
	TTL Duration `yaml:"ttl" json:"ttl"`

	// MaxSize is the maximum file size to cache for this rule.
	MaxSize ByteSize `yaml:"max_size,omitempty" json:"max_size,omitempty"`

	// Priority determines which rule applies when multiple match.
	// Higher priority rules take precedence.
	Priority int `yaml:"priority" json:"priority"`

	// Methods are HTTP methods to cache (default: GET only).
	Methods []string `yaml:"methods,omitempty" json:"methods,omitempty"`

	// ContentTypes are MIME types to cache (empty = all).
	ContentTypes []string `yaml:"content_types,omitempty" json:"content_types,omitempty"`

	// IgnoreQuery ignores query string in cache key generation.
	IgnoreQuery bool `yaml:"ignore_query,omitempty" json:"ignore_query,omitempty"`

	// RespectCacheControl honors Cache-Control headers from origin.
	RespectCacheControl bool `yaml:"respect_cache_control,omitempty" json:"respect_cache_control,omitempty"`

	// StripHeaders removes these headers before caching.
	StripHeaders []string `yaml:"strip_headers,omitempty" json:"strip_headers,omitempty"`
}

RuleConfig defines a caching rule.

type RuleSet

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

RuleSet manages a collection of caching rules.

func LoadRulesFromConfig

func LoadRulesFromConfig(configs []RuleConfig) (*RuleSet, error)

LoadRulesFromConfig loads rules from a slice of RuleConfig.

func NewRuleSet

func NewRuleSet() *RuleSet

NewRuleSet creates a new rule set.

func (*RuleSet) Add

func (rs *RuleSet) Add(rule *Rule)

Add adds a rule to the set.

func (*RuleSet) All

func (rs *RuleSet) All() []*Rule

All returns all rules.

func (*RuleSet) Clear

func (rs *RuleSet) Clear()

Clear removes all rules.

func (*RuleSet) Get

func (rs *RuleSet) Get(name string) *Rule

Get returns a rule by name.

func (*RuleSet) Match

func (rs *RuleSet) Match(req *http.Request) *Rule

Match finds the best matching rule for a request. Returns nil if no rule matches.

func (*RuleSet) MatchHost

func (rs *RuleSet) MatchHost(host string) *Rule

MatchHost finds the best matching rule for a host.

func (*RuleSet) Remove

func (rs *RuleSet) Remove(name string) bool

Remove removes a rule by name.

type SizeReader

type SizeReader struct {
	Reader io.Reader
	Size   int64
}

SizeReader wraps an io.Reader with size information.

func (*SizeReader) Read

func (sr *SizeReader) Read(p []byte) (n int, err error)

Read implements io.Reader.

type Storage

type Storage interface {
	// Get retrieves a cache entry by key.
	// Returns ErrNotFound if the key doesn't exist.
	Get(ctx context.Context, key string) (*Entry, error)

	// Put stores a cache entry.
	// The entry's Body will be fully consumed and the reader closed.
	// Returns ErrEntrySizeExceeded if the content is too large.
	// Returns ErrStorageFull if there's no space and eviction fails.
	Put(ctx context.Context, key string, entry *Entry) error

	// Delete removes a cache entry by key.
	// Returns nil if the key doesn't exist (idempotent).
	Delete(ctx context.Context, key string) error

	// Exists checks if a key exists in the cache.
	// This is a fast check that doesn't load the content.
	Exists(ctx context.Context, key string) bool

	// GetMetadata returns only the metadata for a key (fast lookup).
	// Returns ErrNotFound if the key doesn't exist.
	GetMetadata(ctx context.Context, key string) (*Metadata, error)

	// GetRange retrieves a byte range from a cached entry.
	// Returns ErrNotFound if the key doesn't exist.
	// The returned reader must be closed by the caller.
	GetRange(ctx context.Context, key string, start, end int64) (io.ReadCloser, error)

	// List returns all metadata entries, optionally filtered by domain.
	// If domain is empty, returns all entries.
	// Results are paginated using offset and limit.
	List(ctx context.Context, domain string, offset, limit int) ([]*Metadata, int64, error)

	// Clear removes all entries from the storage.
	Clear(ctx context.Context) error

	// Stats returns storage statistics.
	Stats() StorageStats

	// Start initializes the storage backend.
	// Must be called before any other operations.
	Start(ctx context.Context) error

	// Stop gracefully shuts down the storage backend.
	// Flushes pending writes and releases resources.
	Stop(ctx context.Context) error
}

Storage is the interface for cache storage backends. Implementations must be safe for concurrent access.

type StorageConfig

type StorageConfig struct {
	// Type is the storage type: memory, disk, or tiered.
	Type string `yaml:"type" json:"type"`

	// Tiered contains tiered storage settings.
	Tiered *TieredConfig `yaml:"tiered,omitempty" json:"tiered,omitempty"`

	// Memory contains memory storage settings.
	Memory *MemoryConfig `yaml:"memory,omitempty" json:"memory,omitempty"`

	// Disk contains disk storage settings.
	Disk *DiskConfig `yaml:"disk,omitempty" json:"disk,omitempty"`
}

StorageConfig configures the cache storage backend.

type StorageStats

type StorageStats struct {
	// Entries is the number of cached entries.
	Entries int64 `json:"entries"`

	// TotalSize is the total size of all cached content in bytes.
	TotalSize int64 `json:"total_size_bytes"`

	// MaxSize is the maximum allowed size in bytes.
	MaxSize int64 `json:"max_size_bytes"`

	// UsedPercent is the percentage of storage used.
	UsedPercent float64 `json:"used_percent"`

	// HitCount is the total number of cache hits.
	HitCount int64 `json:"hit_count"`

	// MissCount is the total number of cache misses.
	MissCount int64 `json:"miss_count"`

	// EvictionCount is the total number of evictions.
	EvictionCount int64 `json:"eviction_count"`
}

StorageStats holds storage statistics.

func (*StorageStats) HitRate

func (s *StorageStats) HitRate() float64

HitRate returns the cache hit rate (0.0 to 1.0).

type StorageType

type StorageType string

StorageType represents the type of storage backend.

const (
	// StorageTypeMemory is in-memory LRU storage.
	StorageTypeMemory StorageType = "memory"

	// StorageTypeDisk is file-based disk storage.
	StorageTypeDisk StorageType = "disk"

	// StorageTypeTiered combines memory and disk storage.
	StorageTypeTiered StorageType = "tiered"
)

type TieredConfig

type TieredConfig struct {
	// MemoryThreshold is the size threshold for memory vs disk storage.
	// Files smaller than this are stored in memory, larger in disk.
	MemoryThreshold ByteSize `yaml:"memory_threshold" json:"memory_threshold"`
}

TieredConfig configures tiered storage behavior.

type TieredStorage

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

TieredStorage combines memory and disk storage. Small files are stored in memory, large files on disk.

func NewTieredStorage

func NewTieredStorage(tieredCfg *TieredConfig, memoryCfg *MemoryConfig, diskCfg *DiskConfig) (*TieredStorage, error)

NewTieredStorage creates a new tiered storage.

func (*TieredStorage) Clear

func (t *TieredStorage) Clear(ctx context.Context) error

Clear removes all entries from both tiers.

func (*TieredStorage) Delete

func (t *TieredStorage) Delete(ctx context.Context, key string) error

Delete removes a cache entry from both tiers.

func (*TieredStorage) DiskStats

func (t *TieredStorage) DiskStats() StorageStats

DiskStats returns disk tier statistics.

func (*TieredStorage) Exists

func (t *TieredStorage) Exists(ctx context.Context, key string) bool

Exists checks if a key exists in either tier.

func (*TieredStorage) Get

func (t *TieredStorage) Get(ctx context.Context, key string) (*Entry, error)

Get retrieves a cache entry by key. Checks memory first, then disk.

func (*TieredStorage) GetMetadata

func (t *TieredStorage) GetMetadata(ctx context.Context, key string) (*Metadata, error)

GetMetadata returns metadata from either tier.

func (*TieredStorage) GetRange

func (t *TieredStorage) GetRange(ctx context.Context, key string, start, end int64) (io.ReadCloser, error)

GetRange retrieves a byte range from either tier.

func (*TieredStorage) List

func (t *TieredStorage) List(ctx context.Context, domain string, offset, limit int) ([]*Metadata, int64, error)

List returns metadata from both tiers.

func (*TieredStorage) MemoryStats

func (t *TieredStorage) MemoryStats() StorageStats

MemoryStats returns memory tier statistics.

func (*TieredStorage) Put

func (t *TieredStorage) Put(ctx context.Context, key string, entry *Entry) error

Put stores a cache entry in the appropriate tier.

func (*TieredStorage) Start

func (t *TieredStorage) Start(ctx context.Context) error

Start initializes both storage backends.

func (*TieredStorage) Stats

func (t *TieredStorage) Stats() StorageStats

Stats returns combined storage statistics.

func (*TieredStorage) Stop

func (t *TieredStorage) Stop(ctx context.Context) error

Stop gracefully shuts down both storage backends.

type UnsatisfiableRangeError

type UnsatisfiableRangeError struct {
	Size int64
}

UnsatisfiableRangeError represents a 416 Range Not Satisfiable error.

func (*UnsatisfiableRangeError) ContentRangeHeader

func (e *UnsatisfiableRangeError) ContentRangeHeader() string

ContentRangeHeader returns the Content-Range header for 416 responses.

func (*UnsatisfiableRangeError) Error

func (e *UnsatisfiableRangeError) Error() string

type Validator

type Validator struct{}

Validator handles HTTP cache validation.

func NewValidator

func NewValidator() *Validator

NewValidator creates a new cache validator.

func (*Validator) BuildConditionalRequest

func (v *Validator) BuildConditionalRequest(req *http.Request, entry *Entry)

BuildConditionalRequest adds validation headers to a request. This allows the origin to respond with 304 Not Modified if the cached content is still valid.

func (*Validator) CalculateAge

func (v *Validator) CalculateAge(entry *Entry) time.Duration

CalculateAge calculates the age of a cached entry.

func (*Validator) CalculateFreshness

func (v *Validator) CalculateFreshness(entry *Entry) time.Duration

CalculateFreshness calculates how long an entry will remain fresh.

func (*Validator) CanServeStale

func (v *Validator) CanServeStale(entry *Entry) bool

CanServeStale checks if a stale entry can still be served. Some Cache-Control directives allow serving stale content.

func (*Validator) HandleConditionalResponse

func (v *Validator) HandleConditionalResponse(entry *Entry, resp *http.Response) bool

HandleConditionalResponse processes a response that may be 304 Not Modified. Returns true if the cached entry is still valid and can be used.

func (*Validator) IsFresh

func (v *Validator) IsFresh(entry *Entry) bool

IsFresh checks if a cached entry is still valid/fresh.

func (*Validator) IsStale

func (v *Validator) IsStale(entry *Entry) bool

IsStale checks if an entry is stale (expired but may still be usable).

func (*Validator) NeedsRevalidation

func (v *Validator) NeedsRevalidation(entry *Entry) bool

NeedsRevalidation checks if the entry should be revalidated with origin.

func (*Validator) ShouldCache

func (v *Validator) ShouldCache(req *http.Request, resp *http.Response) bool

ShouldCache determines if a response should be cached.

Jump to

Keyboard shortcuts

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