Skip to main content

Overview

The cache middleware sets Cache-Control headers to control HTTP caching behavior. It helps optimize performance by instructing browsers and CDNs how to cache responses.

Installation

import "github.com/go-mizu/mizu/middlewares/cache"

Quick Start

app := mizu.New()

// Cache for 1 hour
app.Use(cache.New(time.Hour))

Configuration

OptionTypeDescription
MaxAgetime.DurationBrowser cache duration
SMaxAgetime.DurationCDN/proxy cache duration
PublicboolAllow public caching
PrivateboolRestrict to browser only
NoCacheboolRequire revalidation
NoStoreboolDon’t cache at all
NoTransformboolPrevent transformations
MustRevalidateboolMust check freshness
ImmutableboolContent never changes
StaleWhileRevalidatetime.DurationServe stale while fetching
StaleIfErrortime.DurationServe stale on errors

Examples

Basic Caching

// Cache for 1 hour
app.Use(cache.New(time.Hour))

Public Cache (CDN)

// Allow CDN caching
app.Get("/static/*", staticHandler, cache.Public(24*time.Hour))

Private Cache (Browser Only)

// User-specific data, browser only
app.Get("/profile", profileHandler, cache.Private(time.Hour))

Immutable Assets

// Never changes (versioned assets)
app.Get("/assets/*", assetHandler, cache.Immutable(365*24*time.Hour))

Stale-While-Revalidate

// Serve stale for 1 hour while revalidating
app.Get("/api/feed", feedHandler, cache.SWR(time.Minute, time.Hour))

Full Configuration

app.Use(cache.WithOptions(cache.Options{
    MaxAge:               time.Hour,
    SMaxAge:              24 * time.Hour,
    Public:               true,
    MustRevalidate:       true,
    StaleWhileRevalidate: 10 * time.Minute,
}))

Different Cache Strategies

// API: Short cache with revalidation
api := app.Group("/api")
api.Use(cache.SWR(time.Minute, 5*time.Minute))

// Static: Long cache, immutable
static := app.Group("/static")
static.Use(cache.Immutable(365*24*time.Hour))

// Private data: Browser only
private := app.Group("/user")
private.Use(cache.Private(5*time.Minute))

API Reference

func New(maxAge time.Duration) mizu.Middleware
func WithOptions(opts Options) mizu.Middleware
func Public(maxAge time.Duration) mizu.Middleware
func Private(maxAge time.Duration) mizu.Middleware
func Immutable(maxAge time.Duration) mizu.Middleware
func Static(maxAge time.Duration) mizu.Middleware
func SWR(maxAge, stale time.Duration) mizu.Middleware

Common Patterns

Use CaseDirective
Static filespublic, max-age=31536000, immutable
API responsesprivate, max-age=60
CDN cachedpublic, s-maxage=86400, max-age=60
User dataprivate, no-cache
Never cacheno-store

Technical Details

Implementation

The cache middleware operates by constructing and setting the Cache-Control HTTP header based on the provided configuration options. The middleware:
  1. Header Construction: Uses the buildCacheControl function to build the Cache-Control header string from the Options struct
  2. Non-Overriding Behavior: Only sets the Cache-Control header if it hasn’t been set by the handler or previous middleware
  3. Default Fallback: Returns no-cache when no options are specified
  4. Time Conversion: Converts Go time.Duration values to seconds for cache directives (max-age, s-maxage, etc.)

Cache-Control Directives

The middleware supports the following HTTP Cache-Control directives:
  • public: Response may be cached by any cache (browsers, CDNs, proxies)
  • private: Response is intended for a single user and should only be cached by the browser
  • no-cache: Cache must revalidate with the origin server before using cached content
  • no-store: Response must not be stored in any cache
  • no-transform: Intermediaries must not transform the response (e.g., image compression)
  • must-revalidate: Cache must verify the status of stale resources and expired ones should not be used
  • proxy-revalidate: Same as must-revalidate but only for shared caches
  • max-age=N: Maximum time (in seconds) a resource is considered fresh
  • s-maxage=N: Overrides max-age for shared caches (CDNs, proxies)
  • immutable: Resource will never change during its freshness lifetime
  • stale-while-revalidate=N: Cache may serve stale content while revalidating in the background
  • stale-if-error=N: Cache may serve stale content if an error occurs during revalidation

Helper Functions

The package provides several convenience functions that configure common caching strategies:
  • New(maxAge): Basic caching with max-age
  • Public(maxAge): Public caching with max-age
  • Private(maxAge): Private caching with max-age
  • Immutable(maxAge): Immutable public content with max-age
  • Static(maxAge): Alias for Immutable, suitable for static assets
  • SWR(maxAge, stale): Stale-while-revalidate pattern for improved perceived performance

Best Practices

  1. Use appropriate cache strategies for different content types
  2. Leverage stale-while-revalidate for improved user experience
  3. Set immutable for versioned static assets
  4. Use private for user-specific data
  5. Combine with CDN using s-maxage for better edge caching

Testing

The cache middleware includes comprehensive test coverage for all functionality:
Test CaseDescriptionExpected Behavior
TestNewBasic middleware creation with max-ageSets Cache-Control header with max-age=3600 for 1 hour duration
TestWithOptions - public with max-agePublic cache with max-ageContains “public” and “max-age=3600” directives
TestWithOptions - private with max-agePrivate cache with max-ageContains “private” and “max-age=300” directives
TestWithOptions - no-cacheNo-cache directiveContains “no-cache” directive
TestWithOptions - no-storeNo-store directiveContains “no-store” directive
TestWithOptions - must-revalidateMust-revalidate with max-ageContains “must-revalidate” and “max-age=3600” directives
TestWithOptions - immutableImmutable contentContains “public” and “immutable” directives
TestWithOptions - s-maxageShared cache max-ageContains “max-age=3600” and “s-maxage=7200” directives
TestWithOptions - stale-while-revalidateStale-while-revalidate patternContains “max-age=3600” and “stale-while-revalidate=1800” directives
TestPublicPublic cache helper functionCache-Control header contains “public” directive
TestPrivatePrivate cache helper functionCache-Control header contains “private” directive
TestImmutableImmutable cache helper functionCache-Control header contains “immutable” directive
TestStaticStatic assets cache helper functionCache-Control header contains “public” and “immutable” directives
TestSWRStale-while-revalidate helper functionCache-Control header contains “stale-while-revalidate=1800” directive
TestWithOptions_DoesNotOverrideExisting Cache-Control header preservationMiddleware does not override pre-existing Cache-Control headers
TestWithOptions_EmptyEmpty options handlingDefaults to “no-cache” when no options are provided

Security Considerations

  • Sensitive data: Always use private or no-store for sensitive information
  • User-specific content: Never use public for personalized data
  • Authentication: Consider using no-cache or no-store for authenticated routes