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

# Compress

> Response compression middleware supporting gzip and deflate encoding.

## Overview

The `compress` middleware automatically compresses HTTP responses using gzip or deflate encoding when the client supports it. This reduces bandwidth usage and improves load times for text-based content.

Use it when you need:

* Reduced bandwidth for API responses
* Faster page loads for web applications
* Compression for JSON, HTML, CSS, and JavaScript

## Installation

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

## Quick Start

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

// Enable gzip compression
app.Use(compress.Gzip())

// Or enable deflate
app.Use(compress.Deflate())
```

## Configuration

### Options

| Option         | Type       | Default    | Description                       |
| -------------- | ---------- | ---------- | --------------------------------- |
| `Level`        | `int`      | `6`        | Compression level (1-9)           |
| `MinSize`      | `int`      | `1024`     | Minimum response size to compress |
| `ContentTypes` | `[]string` | Text types | Content types to compress         |

## Examples

### Gzip Compression

```go theme={null}
app.Use(compress.Gzip())
```

### Custom Compression Level

```go theme={null}
// Best compression (slower)
app.Use(compress.GzipLevel(9))

// Fastest compression
app.Use(compress.GzipLevel(1))
```

### With Options

```go theme={null}
app.Use(compress.New(compress.Options{
    MinSize: 1000, // Only compress responses > 1KB
    ContentTypes: []string{
        "text/plain",
        "text/html",
        "text/css",
        "application/json",
        "application/javascript",
    },
}))
```

### Auto-Select Encoding

```go theme={null}
// Automatically selects gzip or deflate based on Accept-Encoding
app.Use(compress.New(compress.Options{
    MinSize: 512,
}))
```

## API Reference

### Functions

```go theme={null}
// Gzip creates gzip compression middleware
func Gzip() mizu.Middleware

// GzipLevel creates gzip middleware with specific level
func GzipLevel(level int) mizu.Middleware

// Deflate creates deflate compression middleware
func Deflate() mizu.Middleware

// New creates compression middleware with options
func New(opts Options) mizu.Middleware
```

### Compression Levels

| Level | Description                   |
| ----- | ----------------------------- |
| 1     | Best speed, least compression |
| 6     | Default balance               |
| 9     | Best compression, slowest     |

## Behavior

* Automatically sets `Content-Encoding` header
* Adds `Vary: Accept-Encoding` header
* Skips compression if client doesn't support it
* Skips already-encoded responses
* Skips responses smaller than `MinSize`

## Technical Details

### Implementation Overview

The compress middleware uses a buffering strategy to determine whether compression should be applied:

1. **Buffering Phase**: Responses are buffered until they reach the `MinSize` threshold
2. **Decision Point**: Once the threshold is reached, the middleware checks:
   * If the client supports the requested encoding (via `Accept-Encoding` header)
   * If the content type is compressible (matches `ContentTypes` list)
   * If the response is not already encoded (no existing `Content-Encoding` header)
3. **Compression Phase**: If all checks pass, the appropriate compression writer is applied

### Writer Pooling

The middleware uses `sync.Pool` to efficiently reuse compression writers:

* **Gzip Pool**: Maintains a pool of `gzip.Writer` instances
* **Deflate Pool**: Maintains a pool of `flate.Writer` instances
* Writers are reset and returned to the pool after each request
* This reduces garbage collection pressure and improves performance

### Custom Response Writer

The `compressWriter` wraps the standard `http.ResponseWriter` and provides:

* **Buffering**: Accumulates response data until compression decision is made
* **Lazy Header Writing**: Delays header writing until compression status is determined
* **Automatic Cleanup**: Ensures compression writers are properly closed and returned to pool
* **Flush Support**: Implements `http.Flusher` for streaming responses

### Encoding Selection

When using `New()` with auto-selection:

1. Checks for `gzip` in `Accept-Encoding` header first (preferred)
2. Falls back to `deflate` if gzip is not supported
3. Uses no compression if neither is supported

When using specific functions (`Gzip()`, `Deflate()`):

* Only applies compression if the client explicitly supports the selected encoding

### Default Content Types

The following content types are compressed by default:

* `text/html`, `text/css`, `text/plain`, `text/javascript`, `text/xml`
* `application/json`, `application/javascript`, `application/xml`
* `application/xhtml+xml`, `application/rss+xml`, `application/atom+xml`
* `image/svg+xml`

## Best Practices

* Use level 6 for most applications (good balance)
* Set appropriate `MinSize` to avoid compressing tiny responses
* Only compress text-based content types
* Place before other response-modifying middleware

## Testing

The compress middleware includes comprehensive test coverage for various scenarios:

| Test Case                                | Description                                                 | Expected Behavior                                                                                           |
| ---------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `TestGzip/compresses response`           | Tests basic gzip compression with large response            | Response is compressed with gzip, Content-Encoding header set to "gzip", body can be decompressed correctly |
| `TestGzip/skips without accept-encoding` | Tests behavior when Accept-Encoding header is missing       | Response is not compressed, no Content-Encoding header set                                                  |
| `TestGzip/sets vary header`              | Tests Vary header is properly set                           | Vary header contains "Accept-Encoding"                                                                      |
| `TestGzipLevel`                          | Tests gzip compression with specific level (level 9)        | Response is compressed with specified compression level, Content-Encoding set to "gzip"                     |
| `TestDeflate`                            | Tests deflate compression algorithm                         | Response is compressed with deflate, Content-Encoding header set to "deflate"                               |
| `TestNew_SmallResponse`                  | Tests MinSize threshold with response smaller than limit    | Small responses (\< MinSize) are not compressed                                                             |
| `TestNew_NonCompressibleType`            | Tests content type filtering                                | Non-text content types (e.g., application/octet-stream) are not compressed                                  |
| `TestNew_AlreadyEncoded`                 | Tests handling of pre-encoded responses                     | Existing Content-Encoding header is preserved, no double compression                                        |
| `TestNew_AutoSelectEncoding`             | Tests automatic encoding selection based on Accept-Encoding | Middleware selects gzip or deflate based on client preference, prefers gzip when both available             |

## Related Middlewares

* [cache](/middlewares/cache) - HTTP caching
* [etag](/middlewares/etag) - ETag generation
* [vary](/middlewares/vary) - Vary header management
