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

# Last Modified

> Last-Modified header middleware for conditional requests.

## Overview

The `lastmodified` middleware handles Last-Modified headers and If-Modified-Since conditional requests for efficient caching.

Use it when you need:

* Date-based caching
* Conditional GET requests
* Bandwidth optimization

## Installation

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

## Quick Start

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

app.Use(lastmodified.New())

app.Get("/resource", func(c *mizu.Ctx) error {
    lastmodified.Set(c, resource.UpdatedAt)
    return c.JSON(200, resource)
})
```

## Examples

### Set Last-Modified

```go theme={null}
app.Get("/article/:id", func(c *mizu.Ctx) error {
    article := getArticle(c.Param("id"))
    lastmodified.Set(c, article.UpdatedAt)
    return c.JSON(200, article)
})
```

### Auto Last-Modified

```go theme={null}
app.Use(lastmodified.Auto(func(c *mizu.Ctx) time.Time {
    // Return modification time based on request
    return getModTime(c.Request().URL.Path)
}))
```

### Static Files

```go theme={null}
// Last-Modified is automatic for static files
app.Use(static.New("./public"))
```

## How It Works

1. Handler sets Last-Modified
2. Client receives Last-Modified header
3. Next request includes If-Modified-Since
4. If not modified, returns 304 Not Modified
5. If modified, returns full response

## API Reference

### Functions

```go theme={null}
// New creates Last-Modified middleware
func New() mizu.Middleware

// Set sets Last-Modified for response
func Set(c *mizu.Ctx, t time.Time)

// Auto creates auto Last-Modified middleware
func Auto(getModTime func(*mizu.Ctx) time.Time) mizu.Middleware
```

## Technical Details

The middleware implementation follows HTTP RFC 7232 specifications for conditional requests:

* **Time Format**: Uses HTTP-date format (RFC 5322) for Last-Modified headers
* **Time Comparison**: Truncates to seconds precision for accurate comparison
* **Method Filtering**: Only processes GET and HEAD requests
* **Header Parsing**: Uses `http.ParseTime` which supports multiple date formats
* **304 Response**: Returns Not Modified when If-Modified-Since >= Last-Modified

### Implementation Features

* **Options Configuration**: `Options` struct allows customization with `TimeFunc` and `SkipPaths`
* **Path Skipping**: Can skip specific paths using the `SkipPaths` option
* **Zero Time Handling**: Skips middleware processing when time function returns zero time
* **UTC Normalization**: Automatically converts times to UTC before setting headers

### Helper Functions

* `Static(t time.Time)`: Creates middleware with a fixed modification time
* `Now()`: Uses current time for each request (useful for development/testing)
* `StartupTime()`: Uses application startup time (useful for versioned assets)
* `FromHeader(header string)`: Reads modification time from a custom request header

## Best Practices

* Use with ETag for robust caching
* Set accurate modification times
* Use for static and semi-static content
* Combine with Cache-Control

## Testing

The middleware includes comprehensive test coverage for various scenarios:

| Test Case                        | Description                             | Expected Behavior                            |
| -------------------------------- | --------------------------------------- | -------------------------------------------- |
| TestNew                          | Basic middleware initialization         | Sets Last-Modified header on response        |
| TestIfModifiedSince\_NotModified | Request with matching If-Modified-Since | Returns 304 Not Modified status              |
| TestIfModifiedSince\_Modified    | Request with older If-Modified-Since    | Returns 200 OK with full response            |
| TestWithOptions\_SkipPaths       | Path configured to be skipped           | No Last-Modified header set                  |
| TestSkipPostMethod               | POST request to endpoint                | No Last-Modified header (only GET/HEAD)      |
| TestStatic                       | Static time middleware                  | Returns fixed Last-Modified time             |
| TestNow                          | Current time middleware                 | Sets Last-Modified to current time           |
| TestStartupTime                  | Startup time middleware                 | Consistent time across multiple requests     |
| TestFromHeader                   | Custom header as time source            | Reads and sets time from X-Resource-Modified |
| TestZeroTime                     | Time function returns zero value        | No Last-Modified header set                  |

## Related Middlewares

* [etag](/middlewares/etag) - ETag generation
* [cache](/middlewares/cache) - Cache-Control headers
* [static](/middlewares/static) - Static files
