titip

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

README

Titip

Go Reference Go Version

Titip is a high-throughput, low-allocation HTTP caching middleware for Go applications and API gateways.

Designed for high-concurrency services, Titip reduces backend load by serving cached responses with minimal memory allocation, atomic multi-variant negotiation, RFC-compliant freshness calculations, and fail-open resilience.

Key Features

  • Low-Allocation Design: Reuses internal memory buffers and decompression streams to minimize heap allocations under high concurrency.
  • Fail-Open Resilience: Storage outages, decompression errors, or upstream panics safely bypass to the origin handler (fwd=bypass) or serve stale cache without terminating the process.
  • Session & Privacy Protection: Cold URL misses execute independently without singleflight coalescing, preventing accidental sharing of Set-Cookie or private session headers across concurrent callers.
  • RFC-7234, RFC-9111 & RFC-9213 Compliant: Implements the official Age & Freshness calculation standard (apparent age, corrected initial age, resident time, clock-skew correction, and multi-variant Vary header negotiation).
  • Tiered Cache-Control (RFC 9213): Supports targeted header resolution (Titip-Cache-ControlCDN-Cache-ControlCache-Control), allowing backends to configure edge caching independently from browser caching.
  • RFC-9211 Cache-Status Observability: Structured diagnostics (Cache-Status: titip; hit; ttl=295, fwd=stale, fwd=bypass) with multi-tier cache chaining.
  • Edge Side Includes (ESI): Concurrent fragment assembly, in-process routing, recursive loop protection, and SSRF prevention.
  • Granular Cache Purge API: Invalidation via programmatic Go API (exact URL, wildcard prefixes, surrogate Cache-Tag, soft-purge, or total cache wipeout).
  • Pluggable Architecture: Standard net/http middleware with modular framework adapters and decoupled storage engines.

Architecture

Titip separates metadata from variant payloads to enable atomic multi-variant negotiation (Vary) and short-circuiting with zero redundant body I/O:

[ Incoming Request ] ──► (Primary Key: Scheme + Host + Path + Filtered Query)
                               │
                               ▼
        ┌──────────────────────────────────────────────┐
        │ Stage 1: GetMeta(primaryKey)                 │
        │ Evaluates: Vary headers, freshness, tags     │
        └──────────────────────┬───────────────────────┘
                               │
        ┌──────────────────────┴───────────────────────┐
        │ Match Vary Variant & Evaluate Freshness      │
        └──────┬───────────────────────────────┬───────┘
               │                               │
      (Downstream 304 / HEAD)             (Cache Hit)
               │                               │
               ▼                               ▼
    ┌─────────────────────┐       ┌──────────────────────────────┐
    │ Serve 304 / Headers │       │ Stage 2: GetVariant(pk, vk)  │
    │ (0 Body Payload I/O)│       │ Returns: Headers & Body      │
    └─────────────────────┘       └──────────────┬───────────────┘
                                                 │
                                                 ▼
                                  ┌──────────────────────────────┐
                                  │ LZ4 Decompress & Stream Body │
                                  └──────────────────────────────┘

Modules & Ecosystem

Titip is organized as a multi-module workspace. Each module is versioned independently:

Module Description Documentation
github.com/indragunawan/titip Core caching middleware, state machine, and programmatic Purge API Core Quickstart
github.com/indragunawan/titip/adapter/caddy Native Caddy HTTP middleware directive (titip) & Admin Purge API Caddy Adapter Guide
github.com/indragunawan/titip/storage/redis High-performance Redis (7.4+), Valkey (9.0+), DragonflyDB (1.38+) driver (rueidis) Redis Storage Guide
github.com/indragunawan/titip/storage/redis/caddy Guest storage module for Caddy (titip.storage.redis) Caddy Redis Guide

Quickstart

Install the core package and Redis storage driver:

go get github.com/indragunawan/titip
go get github.com/indragunawan/titip/storage/redis

Wrap any standard net/http handler:

package main

import (
    "context"
    "net/http"
    "time"

    "github.com/redis/rueidis"

    "github.com/indragunawan/titip"
    storageRedis "github.com/indragunawan/titip/storage/redis"
)

func main() {
    // 1. Initialize Redis Client
    client, err := rueidis.NewClient(rueidis.ClientOption{
        InitAddress: []string{"127.0.0.1:6379"},
    })
    if err != nil {
        panic(err)
    }
    defer client.Close()

    // 2. Create Titip Redis Storage
    store, err := storageRedis.New(client, storageRedis.WithKeyPrefix("titip:"))
    if err != nil {
        panic(err)
    }

    // 3. Configure Titip Engine
    cache, err := titip.New(
        store,
        titip.WithCacheStatus(titip.CacheStatusRFC9211),
        titip.WithBackgroundFetchTimeout(125*time.Second),
    )
    if err != nil {
        panic(err)
    }
    defer cache.Close(context.Background())

    // 4. Wrap Standard HTTP Handler
    mux := http.NewServeMux()
    mux.HandleFunc("GET /api/data", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        // Cache publicly for 60 seconds, allow serving stale for 5 minutes during revalidation
        w.Header().Set("Cache-Control", "public, max-age=60, stale-while-revalidate=300")
        w.Header().Set("Cache-Tag", "catalog items")
        w.Write([]byte(`{"message": "hello from origin", "timestamp": "` + time.Now().String() + `"}`))
    })

    http.ListenAndServe(":8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        cache.ServeHTTP(w, r, mux)
    }))
}

Configuration Reference

Initialize Titip with the mandatory storage engine and any functional options via titip.New(store storage.Storage, opts ...Option):

Option Type Default Description
WithCacheStatus(mode) CacheStatusMode CacheStatusSimpleToken Emitted status format (CacheStatusRFC9211, CacheStatusSimpleToken, or CacheStatusNone).
WithCacheKey(cfg) CacheKey {} (standard) Primary cache key generation rules and query parameter filtering.
WithTagHeader(name) string "Cache-Tag" Response header inspected for surrogate cache tags.
WithBackgroundFetchTimeout(d) time.Duration 125s Maximum timeout budget for background revalidations (stale-while-revalidate).
WithStorageTimeout(d) time.Duration 5s Maximum time budget for storage reads/writes before fail-open bypass.
WithRespectClientCacheControl() - (disabled) When enabled, honors client request Cache-Control: no-cache / no-store.
WithoutConvertHeadToGet() - (enabled) Disables converting origin HEAD cache misses to GET to prime the cache with body bytes.
WithAutoInvalidateMutatingMethods() - (disabled) RFC 9111 §4.4: Auto-purges URI cache when mutating requests (POST/PUT/DELETE) succeed.
WithLogger(l) *slog.Logger slog.Default() Structured logger instance for diagnostic events.
WithMetrics(reg) prometheus.Registerer nil Prometheus registry for cache and ESI telemetry.
WithESI(opts...) ...esi.Option disabled Edge Side Includes processing configuration and options.
WithServerTiming() - (disabled) Enables Server-Timing header diagnostics for TTFB tracing in browser DevTools.
WithServerTimingCookie(name, val) string, string "" Restricts Server-Timing header generation to requests matching an exact cookie name and value.

Cache Key & Query Parameter Normalization

Titip constructs normalized cache keys directly without expensive hashing. Use CacheKey to filter query parameters and strip tracking tags to prevent cache fragmentation:

cache, err := titip.New(
    store,
    titip.WithCacheKey(titip.CacheKey{
        // Strips marketing query parameters (utm_*, fbclid, gclid, mc_eid, etc.)
        ExcludeMarketingQueryParams: true,
        // Allowlist specific query parameters to include (or use ExcludedQueryParams for a denylist)
        IncludedQueryParams:    []string{"page", "sort", "filter"},
    }),
)

Cache-Status Diagnostics

Titip supports three Cache-Status modes configured via WithCacheStatus:

1. CacheStatusRFC9211 (Structured Header)

Emits structured diagnostics compliant with RFC 9211, supporting multi-tier cache chaining:

Cache-Status: titip; hit; ttl=240
Cache-Status: "Fastly"; hit, titip; hit; ttl=240
2. CacheStatusSimpleToken (Single Token Header)

Emits a concise single-token status header:

Token Description
HIT Served fresh directly from cache or matched downstream conditional 304 Not Modified.
MISS Cache miss: fetched from origin and stored in cache.
EXPIRED Expired cache entry was synchronously revalidated with origin and refreshed (200 OK).
REVALIDATED Expired cache entry was revalidated with origin via conditional headers (304 Not Modified).
UPDATING Stale cache entry served immediately while revalidating asynchronously in the background (stale-while-revalidate).
STALE Stale cache entry served as failover fallback due to origin error (stale-if-error).
BYPASS Caching explicitly bypassed (mutating method, client no-store, Range request, WebSocket).
DYNAMIC Evaluated for caching, but origin response is uncacheable (Set-Cookie, private, no-store).
3. CacheStatusNone

Disables the Cache-Status response header completely.

Server-Timing Diagnostics

Titip supports the standard Server-Timing header to break down latency in browser DevTools (Chrome Network Timing tab), solving black-box TTFB:

Server-Timing: titip-status;desc="HIT", titip-meta;dur=1.49, titip-body;dur=3.39, titip;dur=4.95
Metrics Reported
Metric Description
titip-status;desc="..." Cache status token (HIT, MISS, EXPIRED, REVALIDATED, STALE, DYNAMIC, BYPASS).
titip-meta;dur=X Stage 1 metadata lookup duration in milliseconds.
titip-body;dur=X Stage 2 body retrieval and LZ4 decompression duration.
titip-origin;dur=X Upstream backend origin fetch duration (on misses or revalidations).
titip-store;dur=X Cache storage duration (LZ4 compression + storage write).
titip-esi;dur=X;desc="N fragments" Edge Side Includes processing duration and fragment count.
titip;dur=X Total Titip processing duration from request arrival.

[!TIP] Titip emits Server-Timing via Header.Add, preserving any existing application-level Server-Timing headers sent by upstream backends (e.g. database query timings). Browsers combine them into a unified list.

To prevent exposing internal infrastructure metrics to the general public, gate header generation with a cookie:

cache, err := titip.New(
    store,
    titip.WithServerTimingCookie("debug_timing", "secret_value"),
)

Cache Invalidation & Purge API

Titip provides a programmatic Go API for Hierarchical Path Purging, Surrogate Tag Purging, and Namespace Invalidation.

Programmatic Go API
// 1. Path Purge (purges /api/products and all its query string variants)
err := cache.Purge(ctx, "/api/products")

// 2. Exact Query Invalidation (purges only ?id=10, leaves other queries intact)
err := cache.Purge(ctx, "http://example.com/api/products?id=10", titip.WithSoftPurge())

// 3. Directory Wildcard (purges all cached paths under /assets/)
err := cache.Purge(ctx, "/assets/*")

// 4. Surrogate Tag Invalidation (invalidates all cached entries matching the tag)
err := cache.PurgeTag(ctx, "catalog")

// 5. Namespace Invalidation (invalidates all cached entries under the configured prefix)
err := cache.PurgeAll(ctx)

Tiered & Targeted Cache-Control (RFC 9213)

Titip supports RFC 9213 Targeted Cache-Control, allowing backend origins to define separate caching rules for the edge/proxy layer versus end-user browsers.

Precedence Hierarchy (First Match Wins)

$$\text{\textbf{Titip-Cache-Control}} ;\longrightarrow; \text{\textbf{CDN-Cache-Control (RFC 9213)}} ;\longrightarrow; \text{\textbf{Cache-Control (RFC 9111)}}$$

HTTP/1.1 200 OK
Titip-Cache-Control: public, max-age=86400, stale-while-revalidate=3600
Cache-Control: private, no-store
  • Titip (Intermediary): Caches the response in storage for 24 hours (max-age=86400), shielding the origin from load.
  • Client (Browser): Receives Cache-Control: private, no-store, preventing sensitive data from persisting in local browser history.

Edge Side Includes (ESI)

Titip includes an Edge Side Includes (ESI) engine with parallel fragment fetching, circular loop protection, and SSRF prevention.

When ESI is active, Titip advertises capability to upstream origins by sending Surrogate-Capability: titip="ESI/1.0" per Edge Side Includes (ESI) specifications. Origins can respond with Surrogate-Control: content="ESI/1.0" to direct ESI processing.

For standalone package documentation and options reference, see ESI Package Guide.

cache, err := titip.New(
    store,
    titip.WithESI(
        esi.WithInternalFetcher(esi.HandlerFetcher(router)),
        esi.WithMaxDepth(3),
        esi.WithMaxTimeout(5 * time.Second),
    ),
)
Supported ESI Tags & Syntax
Syntax Description
<esi:include src="/fragment" /> Self-closing fragment include. Fetched concurrently.
<esi:include src="/fragment" alt="/fallback" onerror="continue" /> Include with fallback URL on failure or silent omission (onerror="continue").
<esi:include src="...">Fallback HTML</esi:include> Paired include with inline fallback block.
<!--esi <div>Visible only when ESI active</div> --> Unescapes enclosed HTML comments when ESI is enabled.
<esi:remove><p>Placeholder</p></esi:remove> Strips placeholder content intended for non-ESI clients.
<!--esi-comment text="..." --> Strips internal comments without emitting bytes.
ESI Functional Options (esi.Option)
Option Builder Default Description
esi.WithHeaderRequired() (disabled) Process ESI only when origin sets Surrogate-Control: content="ESI/1.0".
esi.WithInternalFetcher(fn) nil Custom hook for in-memory virtual subrequests (e.g. esi.HandlerFetcher(r)).
esi.WithMaxDepth(uint32) 3 Maximum nesting depth for recursive ESI includes.
esi.WithMaxTimeout(duration) 30s Maximum time budget per fragment include fetch.
esi.WithMaxConcurrentRequests(int) 8 Maximum concurrent fetch goroutines per document.
esi.WithAllowPrivateIPs() (disabled) SSRF guard: allows requests to private, loopback, and link-local IP addresses.
esi.WithAllowedHosts(...string) [] List of allowed external hosts for domain includes (empty allows all public hosts).
esi.WithAllowPrivateIPsForAllowedHosts() (disabled) Permits private IPs specifically for explicitly allowed hosts.
esi.WithMaxResponseSize(int64) 10MB Maximum allowed fragment body size in bytes.
esi.WithoutForwardCookies() (forwarding enabled) Disables forwarding Set-Cookie headers from fragment responses to the client.
esi.WithPreserveETag() (disabled) Weakens origin ETag (W/"...") and preserves Last-Modified for downstream 304. By default, strips ETag/Last-Modified downstream to guarantee fresh fragment execution.
esi.WithIncludeErrorMarker(string) "" HTML placeholder rendered on unhandled fetch errors.

Observability & Metrics

Titip exports comprehensive Prometheus metrics for request traffic, cache latencies, purge invalidations, and ESI fragment processing:

// Register with a Prometheus registry:
cache, err := titip.New(
    store,
    titip.WithMetrics(prometheus.DefaultRegisterer),
)
Exported Metrics
Metric Name Type Labels Description
titip_requests_total Counter status (hit, miss, stale_hit, revalidated, bypass, error) Total HTTP requests processed by Titip caching middleware.
titip_request_duration_seconds Histogram status Request latency distribution in seconds across cache statuses.
titip_purges_total Counter type (url, tag, all), mode (hard, soft), status (success, error) Total purge operations executed by type and mode.
titip_purged_entries_total Counter type (url, tag, all), mode (hard, soft) Total logical cache entries invalidated by purge operations.
titip_esi_fragments_total Counter status (success, fallback, error) Total ESI fragment includes processed (enabled when ESI is active).
titip_esi_duration_seconds Histogram mode (in_process, outbound) Latency distribution of ESI fragment fetching and document splicing.
# Example Prometheus Scrape Output:
titip_requests_total{status="hit"} 4125
titip_requests_total{status="miss"} 102
titip_requests_total{status="stale_hit"} 18
titip_requests_total{status="revalidated"} 12
titip_requests_total{status="bypass"} 5
titip_requests_total{status="error"} 0

titip_purges_total{mode="soft",status="success",type="url"} 45
titip_purged_entries_total{mode="soft",type="url"} 45

titip_esi_fragments_total{status="success"} 230
titip_esi_duration_seconds_bucket{mode="in_process",le="0.005"} 225

Testing & Concurrency Standards

Titip enforces continuous race detection and zero-leak concurrency standards:

# Run all unit and concurrency stress tests with race detector
go test -race -count=50 -v ./...

Contributing

We welcome contributions for new framework adapters and storage drivers.

Please read our Contributing Guide for architectural guidelines, interface contracts, and testing standards.

License

This project is licensed under the Apache 2.0 License.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidOption is returned when an invalid configuration option is provided to New.
	ErrInvalidOption = errors.New("titip: invalid option")
)
View Source
var (
	// ErrStorageRequired is returned by New when the mandatory storage parameter is nil.
	ErrStorageRequired = errors.New("titip: storage is required")
)

Functions

This section is empty.

Types

type CacheKey added in v0.2.0

type CacheKey struct {
	// IncludeProtocol includes the request scheme ("http" or "https") in the cache key.
	// When true, HTTP and HTTPS requests reference distinct cache entries.
	IncludeProtocol bool

	// ExcludeHost excludes the HTTP Host / domain from the cache key.
	// When true, Host is omitted so multiple domains serving identical content share cache entries.
	ExcludeHost bool

	// ExcludeQuery removes all query parameters from the cache key.
	// When true, the query component is stripped so requests with different query strings share cache.
	ExcludeQuery bool

	// PreserveQueryOrder preserves the original query parameter ordering from the request URL.
	// When true, query parameter order is preserved as received from the client instead of sorting alphabetically.
	PreserveQueryOrder bool

	// IncludedQueryParams specifies an allowlist of query parameter names to include in the cache key.
	// If set, only these specific parameters are included in the cache key.
	IncludedQueryParams []string

	// ExcludedQueryParams specifies a denylist of query parameter names to exclude from the cache key.
	// If set, all query parameters except these are included in the cache key.
	ExcludedQueryParams []string

	// ExcludeMarketingQueryParams filters out standard advertising and tracking query parameters
	// including all utm_* prefix parameters (e.g. utm_source, utm_campaign, utm_id, utm_content)
	// and common advertising click IDs (gclid, fbclid, ttclid, msclkid, etc.).
	// When true, marketing tracking parameters are stripped from the cache key.
	ExcludeMarketingQueryParams bool

	// IncludedHeaderNames specifies request header names whose values are appended to the primary cache key.
	//
	// Note: Do NOT include headers that the origin already manages via the HTTP "Vary" header
	// (e.g. "Accept-Encoding"), as Titip handles origin Vary negotiation automatically.
	//
	// Warning: NEVER include authentication tokens or credentials (e.g. "Authorization").
	// Specifying headers with high cardinality or wide ranges of values dramatically lowers the
	// cache hit rate and causes higher eviction churn.
	//
	// Best used for low-cardinality headers or A/B experiment buckets (e.g. "X-Region", "X-Experiment-Bucket").
	IncludedHeaderNames []string

	// IncludedCookieNames specifies cookie names whose values are appended to the cache key.
	//
	// Warning: NEVER include session identifiers, auth cookies, or credentials.
	// Including unique per-user cookies effectively creates per-user caches, destroying hit rates.
	//
	// Best used for low-cardinality user preferences or A/B testing groups (e.g. "ab_group", "currency", "theme", "locale").
	IncludedCookieNames []string

	// CaseInsensitivePath normalizes the URL path to lowercase in the primary cache key.
	// When true, requests with different path casing (e.g. /Products/Shoes vs /products/shoes) share the same cache entry.
	CaseInsensitivePath bool

	// IncludedQueryParamValues specifies an allowlist of specific parameter values.
	// A parameter key in this map is only included in the cache key if its value matches one of the specified allowed values.
	// Any value not in the list is omitted from the cache key.
	IncludedQueryParamValues map[string][]string
}

CacheKey defines the rules for assembling zero-hash canonical cache keys.

Every cached request automatically receives a cache key. A zero-value CacheKey{} or omitting WithCacheKey applies the standard RFC-compliant default: host included, protocol excluded, case-sensitive path, all query parameters retained, and sorted alphabetically.

type CacheStatusMode

type CacheStatusMode int

CacheStatusMode specifies the format of the emitted Cache-Status header.

const (
	// CacheStatusSimpleToken outputs single-token status header (e.g. HIT, MISS, EXPIRED, REVALIDATED, UPDATING, STALE, BYPASS, DYNAMIC) by default.
	CacheStatusSimpleToken CacheStatusMode = iota
	// CacheStatusRFC9211 outputs structured RFC-9211 Cache-Status header (e.g. Cache-Status: titip; hit; ttl=240).
	CacheStatusRFC9211
	// CacheStatusNone disables cache status header generation.
	CacheStatusNone
)

type Option

type Option func(*config) error

Option configures Titip middleware options.

func WithAutoInvalidateMutatingMethods

func WithAutoInvalidateMutatingMethods() Option

WithAutoInvalidateMutatingMethods enables automatic invalidation of cached GET entries when successful mutating requests (POST, PUT, DELETE, PATCH) are received for the URI, matching the mandatory invalidation behavior defined in RFC 9111 Section 4.4. By default, this is disabled so applications can rely on explicit tag-based (Cache-Tag) or URL invalidation.

func WithBackgroundFetchTimeout added in v0.2.0

func WithBackgroundFetchTimeout(d time.Duration) Option

WithBackgroundFetchTimeout configures the maximum timeout for asynchronous background revalidation (stale-while-revalidate) origin fetches (defaults to 125s). Set to 0 to disable background timeout enforcement.

func WithCacheKey added in v0.2.0

func WithCacheKey(k CacheKey) Option

WithCacheKey customizes the rules for assembling canonical cache keys (such as query parameter filtering, marketing tag removal, and header/cookie dimensions).

A cache key is always automatically generated for every request. If WithCacheKey is omitted, Titip applies standard default key generation (protocol-agnostic, host-aware, case-sensitive path, all query parameters retained, and sorted alphabetically).

func WithCacheStatus added in v0.3.0

func WithCacheStatus(mode CacheStatusMode) Option

WithCacheStatus configures the Cache-Status header emission mode.

func WithESI

func WithESI(opts ...esi.Option) Option

WithESI enables ESI processing with the provided ESI options. If no options are provided, ESI is enabled with safe production defaults.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger configures the structured slog.Logger.

func WithMetrics

func WithMetrics(reg prometheus.Registerer) Option

WithMetrics configures the Prometheus metrics registerer.

func WithRespectClientCacheControl

func WithRespectClientCacheControl() Option

WithRespectClientCacheControl enables respecting client request Cache-Control directives (e.g. no-cache, no-store). By default, client cache directives are ignored to protect origin servers.

func WithServerTiming added in v0.3.0

func WithServerTiming() Option

WithServerTiming enables Server-Timing header diagnostics for TTFB tracing in browser DevTools.

func WithServerTimingCookie added in v0.3.0

func WithServerTimingCookie(name, value string) Option

WithServerTimingCookie enables Server-Timing header generation gated by an exact cookie name and value match.

func WithStorageTimeout

func WithStorageTimeout(d time.Duration) Option

WithStorageTimeout configures maximum timeout for storage operations (defaults to 5s).

func WithTagHeader added in v0.3.0

func WithTagHeader(name string) Option

WithTagHeader configures the response header inspected for cache tags (defaults to "Cache-Tag").

func WithoutConvertHeadToGet added in v0.3.0

func WithoutConvertHeadToGet() Option

WithoutConvertHeadToGet disables converting origin HEAD cache misses and revalidations to GET. By default, HEAD misses are converted to GET to prime the cache with body bytes. When disabled, HEAD misses query the origin as HEAD and are not saved to cache.

type PurgeOption

type PurgeOption func(*purgeConfig)

PurgeOption configures Purge, PurgeTag, or PurgeAll operations.

func WithSoftPurge

func WithSoftPurge() PurgeOption

WithSoftPurge marks entries as stale rather than evicting immediately (safe thundering-herd mode). The stale copy is preserved for stale-if-error fallback if the origin subsequently fails.

type Titip

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

Titip represents the HTTP caching middleware instance.

func New

func New(store storage.Storage, opts ...Option) (*Titip, error)

New creates a new Titip caching middleware instance. The store parameter is mandatory. If store is nil, ErrStorageRequired is returned.

func (*Titip) Close

func (t *Titip) Close(ctx context.Context) error

Close cleanly shuts down the middleware, awaiting background SWR revalidations.

func (*Titip) Purge

func (t *Titip) Purge(ctx context.Context, target string, opts ...PurgeOption) (int64, error)

Purge invalidates cache entries matching the specified path or URL (and its query variations).

The target supports the following formats:

  • "/api/products" — purges the path and ALL query string variations
  • "https://example.com/api/products" — host-scoped path purge (include domain in target to scope by host)
  • "https://example.com/api?id=42" — exact query variant (O(1) exact delete)
  • "/api/products?id=42" — exact query variant (exact delete if ExcludeHost=true, or across all hosts)
  • "/" — purges the homepage only

Note: Purge treats any asterisks in the path literally (not as a wildcard). To purge a path hierarchy or directory prefix, use PurgePrefix().

By default, purge is a hard-delete (immediate physical eviction). Use WithSoftPurge() to mark entries as stale instead for safe thundering-herd protection.

Returns the total number of logical cache entries invalidated.

func (*Titip) PurgeAll

func (t *Titip) PurgeAll(ctx context.Context) (int64, error)

PurgeAll deletes every cache entry in the configured storage namespace.

func (*Titip) PurgePrefix added in v0.3.0

func (t *Titip) PurgePrefix(ctx context.Context, prefix string, opts ...PurgeOption) (int64, error)

PurgePrefix invalidates cache entries matching the specified path or URL prefix (Cloudflare-style).

Behavior:

  • "/assets/" (with trailing slash) — directory prefix: purges all child paths under /assets/ (does not touch /assets-v2)
  • "/assets" (without trailing slash) — raw string prefix: purges /assets, /assets/*, AND /assets-v2
  • "/" — purges the entire cache namespace (supports WithSoftPurge())
  • "https://example.com/assets/" — host-scoped prefix purge

By default, purge is a hard-delete (immediate physical eviction). Use WithSoftPurge() to mark entries as stale instead for safe thundering-herd protection.

Returns the total number of logical cache entries invalidated.

func (*Titip) PurgeTag

func (t *Titip) PurgeTag(ctx context.Context, tag string, opts ...PurgeOption) (int64, error)

PurgeTag invalidates all cache entries tagged with the specified tag. The tag is treated as a literal string. To wipe the entire cache namespace, use PurgeAll.

func (*Titip) ServeHTTP

func (t *Titip) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.Handler)

ServeHTTP executes the Titip caching middleware pipeline for a request and forwards to next on cache miss or revalidation.

Directories

Path Synopsis
adapter
caddy module
internal
redis module
redis/caddy module

Jump to

Keyboard shortcuts

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