> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Cache

> Cache-Control header middleware for HTTP caching.

## 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

```go theme={null}
import "github.com/go-mizu/mizu/middlewares/cache"
```

## Quick Start

```go theme={null}
app := mizu.New()

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

## Configuration

| Option                 | Type            | Description                |
| ---------------------- | --------------- | -------------------------- |
| `MaxAge`               | `time.Duration` | Browser cache duration     |
| `SMaxAge`              | `time.Duration` | CDN/proxy cache duration   |
| `Public`               | `bool`          | Allow public caching       |
| `Private`              | `bool`          | Restrict to browser only   |
| `NoCache`              | `bool`          | Require revalidation       |
| `NoStore`              | `bool`          | Don't cache at all         |
| `NoTransform`          | `bool`          | Prevent transformations    |
| `MustRevalidate`       | `bool`          | Must check freshness       |
| `Immutable`            | `bool`          | Content never changes      |
| `StaleWhileRevalidate` | `time.Duration` | Serve stale while fetching |
| `StaleIfError`         | `time.Duration` | Serve stale on errors      |

## Examples

### Basic Caching

```go theme={null}
// Cache for 1 hour
app.Use(cache.New(time.Hour))
```

### Public Cache (CDN)

```go theme={null}
// Allow CDN caching
app.Get("/static/*", staticHandler, cache.Public(24*time.Hour))
```

### Private Cache (Browser Only)

```go theme={null}
// User-specific data, browser only
app.Get("/profile", profileHandler, cache.Private(time.Hour))
```

### Immutable Assets

```go theme={null}
// Never changes (versioned assets)
app.Get("/assets/*", assetHandler, cache.Immutable(365*24*time.Hour))
```

### Stale-While-Revalidate

```go theme={null}
// Serve stale for 1 hour while revalidating
app.Get("/api/feed", feedHandler, cache.SWR(time.Minute, time.Hour))
```

### Full Configuration

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

### Different Cache Strategies

```go theme={null}
// 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

```go theme={null}
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 Case      | Directive                             |
| ------------- | ------------------------------------- |
| Static files  | `public, max-age=31536000, immutable` |
| API responses | `private, max-age=60`                 |
| CDN cached    | `public, s-maxage=86400, max-age=60`  |
| User data     | `private, no-cache`                   |
| Never cache   | `no-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 Case                                | Description                                | Expected Behavior                                                     |
| ---------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------- |
| TestNew                                  | Basic middleware creation with max-age     | Sets Cache-Control header with max-age=3600 for 1 hour duration       |
| TestWithOptions - public with max-age    | Public cache with max-age                  | Contains "public" and "max-age=3600" directives                       |
| TestWithOptions - private with max-age   | Private cache with max-age                 | Contains "private" and "max-age=300" directives                       |
| TestWithOptions - no-cache               | No-cache directive                         | Contains "no-cache" directive                                         |
| TestWithOptions - no-store               | No-store directive                         | Contains "no-store" directive                                         |
| TestWithOptions - must-revalidate        | Must-revalidate with max-age               | Contains "must-revalidate" and "max-age=3600" directives              |
| TestWithOptions - immutable              | Immutable content                          | Contains "public" and "immutable" directives                          |
| TestWithOptions - s-maxage               | Shared cache max-age                       | Contains "max-age=3600" and "s-maxage=7200" directives                |
| TestWithOptions - stale-while-revalidate | Stale-while-revalidate pattern             | Contains "max-age=3600" and "stale-while-revalidate=1800" directives  |
| TestPublic                               | Public cache helper function               | Cache-Control header contains "public" directive                      |
| TestPrivate                              | Private cache helper function              | Cache-Control header contains "private" directive                     |
| TestImmutable                            | Immutable cache helper function            | Cache-Control header contains "immutable" directive                   |
| TestStatic                               | Static assets cache helper function        | Cache-Control header contains "public" and "immutable" directives     |
| TestSWR                                  | Stale-while-revalidate helper function     | Cache-Control header contains "stale-while-revalidate=1800" directive |
| TestWithOptions\_DoesNotOverride         | Existing Cache-Control header preservation | Middleware does not override pre-existing Cache-Control headers       |
| TestWithOptions\_Empty                   | Empty options handling                     | Defaults 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

## Related Middlewares

* [nocache](/middlewares/nocache) - Prevent caching
