Documentation
¶
Overview ¶
Package compression provides middleware for HTTP response compression.
This middleware automatically compresses HTTP responses using gzip, deflate, or brotli compression algorithms based on client Accept-Encoding headers. It reduces bandwidth usage and improves response times for text-based content.
Basic Usage ¶
import "rivaas.dev/middleware/compression" r := router.MustNew() r.Use(compression.New())
Supported Algorithms ¶
The middleware supports multiple compression algorithms:
- gzip: Standard gzip compression (widely supported)
- deflate: Deflate compression (legacy support)
- brotli: Brotli compression (better compression ratio, modern browsers)
The middleware automatically selects the best algorithm based on client Accept-Encoding headers and configured preferences.
Configuration Options ¶
- Level: Compression level (1-9, higher = better compression but slower)
- MinSize: Minimum response size to compress (default: 1KB)
- ContentTypes: Content types to compress (default: text/*, application/json, etc.)
- ExcludePaths: Paths to exclude from compression (e.g., /metrics)
- Logger: Optional logger for compression events
Content Type Filtering ¶
By default, the middleware compresses text-based content types:
- text/*
- application/json
- application/javascript
- application/xml
- application/xhtml+xml
Binary content types (images, videos, etc.) are excluded by default.
Index ¶
- func New(opts ...Option) router.HandlerFunc
- type Option
- func WithBrotliDisabled() Option
- func WithBrotliLevel(level int) Option
- func WithExcludeContentTypes(contentTypes ...string) Option
- func WithExcludeExtensions(extensions ...string) Option
- func WithExcludePaths(paths ...string) Option
- func WithGzipDisabled() Option
- func WithGzipLevel(level int) Option
- func WithLogger(logger *slog.Logger) Option
- func WithMinSize(size int) Option
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func New ¶
func New(opts ...Option) router.HandlerFunc
New returns a middleware that compresses HTTP responses using gzip and/or Brotli. It automatically detects client support and selects the best encoding based on Accept-Encoding header with q-value negotiation.
Features:
- Automatic gzip and Brotli compression with quality-value negotiation
- Configurable compression levels for both algorithms
- Minimum size threshold with buffering to avoid compressing small responses
- Path and content-type exclusions
- Writer pooling for reduced allocations
- Skips compression for 204, 304, 206, SSE, and gRPC
- Sets Vary: Accept-Encoding header
- Respects existing Content-Encoding headers (proxying)
Basic usage:
r := router.MustNew() r.Use(compression.New())
With custom compression levels:
r.Use(compression.New(
compression.WithGzipLevel(gzip.BestCompression),
compression.WithBrotliLevel(5),
))
Disable Brotli (gzip only):
r.Use(compression.New(
compression.WithBrotliDisabled(),
))
Exclude certain paths:
r.Use(compression.New(
compression.WithExcludePaths("/metrics", "/stream"),
))
Exclude already compressed formats:
r.Use(compression.New(
compression.WithExcludeExtensions(".jpg", ".png", ".gif", ".zip"),
compression.WithExcludeContentTypes("image/jpeg", "image/png"),
))
Types ¶
type Option ¶
type Option func(*config)
Option defines functional options for compression middleware configuration.
func WithBrotliDisabled ¶
func WithBrotliDisabled() Option
WithBrotliDisabled disables Brotli compression (gzip only).
Example:
compression.New(compression.WithBrotliDisabled())
func WithBrotliLevel ¶
WithBrotliLevel sets the Brotli compression level. Valid values: 0 (no compression) to 11 (best compression). For dynamic content (JSON/text), use 4-5. Higher levels are CPU-expensive. Default: 4 (conservative for dynamic content)
Example:
compression.New(compression.WithBrotliLevel(5))
func WithExcludeContentTypes ¶
WithExcludeContentTypes sets content types that should not be compressed. Already compressed content types don't benefit from compression.
Example:
compression.New(compression.WithExcludeContentTypes("image/jpeg", "image/png", "application/zip"))
func WithExcludeExtensions ¶
WithExcludeExtensions sets file extensions that should not be compressed. Already compressed formats don't benefit from compression. Default: none (but should typically exclude .jpg, .png, .gif, .zip, etc.)
Example:
compression.New(compression.WithExcludeExtensions(".jpg", ".png", ".gif", ".zip", ".gz"))
func WithExcludePaths ¶
WithExcludePaths sets paths that should not be compressed. Useful for endpoints that already serve compressed content or streaming responses.
Example:
compression.New(compression.WithExcludePaths("/metrics", "/stream"))
func WithGzipDisabled ¶
func WithGzipDisabled() Option
WithGzipDisabled disables gzip compression (Brotli only).
Example:
compression.New(compression.WithGzipDisabled())
func WithGzipLevel ¶
WithGzipLevel sets the gzip compression level. Valid values: 0 (no compression) to 9 (best compression). Default: gzip.DefaultCompression (-1, which is typically level 6)
Example:
compression.New(compression.WithGzipLevel(gzip.BestCompression))
func WithLogger ¶
WithLogger sets the slog.Logger for error logging. If not provided, errors will be silently ignored.
Uses the standard library's log/slog package for structured logging:
import "log/slog" logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) compression.New(compression.WithLogger(logger))
Example:
import "log/slog" logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) r.Use(compression.New(compression.WithLogger(logger)))
func WithMinSize ¶
WithMinSize sets the minimum response size to compress (in bytes).
DESIGN DECISION: This feature is intentionally NOT implemented.
Why minSize is not implemented:
- Requires buffering entire response before compression decision
- Adds memory overhead (buffer per request)
- Adds latency (wait for full response before sending)
- Breaks streaming responses
- Modern networks handle small compressed payloads efficiently
Alternative approaches (recommended):
- Use WithExcludePaths for small endpoints
- Use WithExcludeContentTypes for small data types
- Let CDN/reverse proxy handle compression (nginx, CloudFlare)
If you truly need minSize, implement at the reverse proxy level where buffering is already happening (nginx, CloudFlare, etc.)
This option exists for API compatibility but is a no-op. Default: 1024 (1KB, not enforced)
Example:
compression.New(compression.WithMinSize(2048)) // No effect (by design)