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

# Timeout

> Request timeout middleware for preventing long-running requests.

## Overview

The `timeout` middleware enforces a maximum duration for request processing. If a handler takes too long, the request is cancelled and an error response is returned.

## Installation

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

## Quick Start

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

// 30 second timeout
app.Use(timeout.New(30 * time.Second))
```

## Configuration

| Option         | Type                    | Default                 | Description              |
| -------------- | ----------------------- | ----------------------- | ------------------------ |
| `Timeout`      | `time.Duration`         | `30s`                   | Maximum request duration |
| `ErrorHandler` | `func(*mizu.Ctx) error` | -                       | Custom timeout handler   |
| `ErrorMessage` | `string`                | `"Service Unavailable"` | Error message            |

## Examples

### Basic Timeout

```go theme={null}
app.Use(timeout.New(30 * time.Second))
```

### Custom Error Handler

```go theme={null}
app.Use(timeout.WithOptions(timeout.Options{
    Timeout: 10 * time.Second,
    ErrorHandler: func(c *mizu.Ctx) error {
        return c.JSON(504, map[string]string{
            "error": "Request timed out",
        })
    },
}))
```

### Different Timeouts Per Route

```go theme={null}
// Global: 30s
app.Use(timeout.New(30 * time.Second))

// Slow endpoint: 5 minutes
app.Post("/export", exportHandler, timeout.New(5*time.Minute))

// Fast endpoint: 5 seconds
app.Get("/health", healthHandler, timeout.New(5*time.Second))
```

### Check Context in Handler

```go theme={null}
app.Get("/data", func(c *mizu.Ctx) error {
    for i := 0; i < 100; i++ {
        select {
        case <-c.Context().Done():
            return c.Context().Err() // Timeout reached
        default:
            processItem(i)
        }
    }
    return c.JSON(200, results)
})
```

## API Reference

```go theme={null}
func New(timeout time.Duration) mizu.Middleware
func WithOptions(opts Options) mizu.Middleware
```

## How It Works

1. Creates a context with deadline
2. Runs handler in goroutine
3. Returns whichever completes first:
   * Handler completion
   * Timeout expiration (returns 503)

## Technical Details

### Implementation

The timeout middleware uses Go's `context.WithTimeout` to enforce request deadlines:

1. **Context Creation**: Creates a context with deadline using `context.WithTimeout(c.Context(), opts.Timeout)`
2. **Request Update**: Replaces the request's context with the timeout context
3. **Goroutine Execution**: Runs the next handler in a separate goroutine to enable timeout detection
4. **Channel Communication**: Uses a buffered channel to receive the handler's result
5. **Select Statement**: Races between handler completion and context cancellation
   * If handler completes first, returns the result
   * If timeout occurs first, calls error handler or returns 503 Service Unavailable

### Default Values

* **Timeout Duration**: 30 seconds (when `Timeout <= 0`)
* **Error Message**: "Service Unavailable"
* **HTTP Status**: 503 Service Unavailable (when no custom error handler is provided)

### Concurrency Safety

The middleware safely handles concurrent requests by:

* Using a buffered channel (size 1) to prevent goroutine leaks
* Properly deferring the context cancel function to release resources
* Isolating each request's timeout context

## Best Practices

* Set reasonable timeouts based on expected duration
* Use longer timeouts for file uploads/downloads
* Check context in long-running operations
* Return 503 (Service Unavailable) on timeout

## Testing

### Test Cases

| Test Case                         | Description                                       | Expected Behavior                                                                     |
| --------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `TestNew/times out slow request`  | Handler takes longer than timeout (200ms vs 50ms) | Returns 503 Service Unavailable status                                                |
| `TestNew/allows fast request`     | Handler completes before timeout                  | Returns 200 OK with correct response body                                             |
| `TestWithOptions_ErrorHandler`    | Custom error handler is provided                  | Calls custom error handler, returns 504 Gateway Timeout with JSON error               |
| `TestWithOptions_CustomMessage`   | Custom error message is set                       | Returns custom message "Request took too long" in response body                       |
| `TestWithOptions_DefaultTimeout`  | No timeout specified in options                   | Creates middleware with 30 second default timeout                                     |
| `TestTimeout_ContextCancellation` | Handler checks context cancellation               | Context is cancelled when timeout occurs, handler can detect via `c.Context().Done()` |

## Related Middlewares

* [recover](/middlewares/recover) - Panic recovery
* [circuitbreaker](/middlewares/circuitbreaker) - Failure handling
