compression

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package compression provides express middleware that gzip-compresses response bodies for clients that advertise gzip support via the Accept-Encoding request header. It is the Go analogue of the Node compression middleware (expressjs/compression), packaged as a drop-in express.Handler, and it trades a small amount of CPU for a large reduction in bytes on the wire for compressible payloads such as HTML, JSON, CSS, and JavaScript.

Use this middleware when you serve text-based responses to bandwidth-limited or latency-sensitive clients and want smaller transfers without touching your handlers. Mount it once near the top of the chain with app.Use so that it wraps every downstream response, or attach it to a specific router or path prefix to compress only part of the tree. Because it buffers the body to make a size-based decision, it is best suited to ordinary buffered responses rather than long-lived streams; place any handler that needs raw, unbuffered access to the response writer ahead of it.

Operationally the middleware runs early but does its real work after the downstream handler returns. On each request it first inspects Accept-Encoding: if the client does not list gzip it calls next() and leaves the response completely untouched. Otherwise it swaps res.Writer for an internal capturing writer, calls next() so the handler writes as usual, and then restores the original writer. The captured status code and body are then examined to decide whether compression is worthwhile. When it does compress, it sets Content-Encoding: gzip, adds Vary: Accept-Encoding so caches key on the negotiated encoding, deletes the now-incorrect Content-Length, writes the captured status, and streams the gzipped bytes to the original writer.

Several conditions short-circuit compression and cause the buffered body to be written through verbatim: a body smaller than MinLength (default DefaultMinLength, 256 bytes), or a response that already carries a Content-Encoding header (for example an image or a pre-compressed asset). The compression Level defaults to gzip.DefaultCompression and may be set to any value from gzip.BestSpeed to gzip.BestCompression; an invalid level that causes gzip.NewWriterLevel to fail results in the uncompressed body being written as a safe fallback. Because the body is buffered in memory before being flushed, very large responses hold their full size in memory for the duration of the request.

Compared with the Node original, this port keeps the same negotiate, buffer, and conditionally-encode model and the same Vary and Content-Length handling, but is deliberately narrower in scope. It supports only gzip (not deflate or brotli), it does not consult a per-Content-Type filter function to decide compressibility, and it does not expose a streaming flush hook; the decision to compress rests solely on Accept-Encoding, the body length, and any existing Content-Encoding.

Example

Example demonstrates gzip-compressing responses with the compression middleware. It builds an express application, mounts the middleware with a low MinLength so even a modest body qualifies, and registers a handler that sends a repetitive, highly compressible payload. The request advertises gzip support through its Accept-Encoding header, which is the signal the middleware negotiates on. Because the body exceeds MinLength and carries no existing Content-Encoding, the middleware buffers it, gzips it, and sets Content-Encoding: gzip together with Vary: Accept-Encoding on the response. The example then prints the negotiated Content-Encoding header, which is deterministic regardless of the exact compressed bytes.

package main

import (
	"fmt"
	"net/http/httptest"
	"strings"

	"github.com/malcolmston/express"
	"github.com/malcolmston/express/middleware/compression"
)

func main() {
	app := express.New()
	app.Use(compression.New(compression.Options{MinLength: 16}))
	app.Get("/", func(req *express.Request, res *express.Response, next express.Next) {
		res.Send(strings.Repeat("hello world ", 64))
	})

	req := httptest.NewRequest("GET", "/", nil)
	req.Header.Set("Accept-Encoding", "gzip, deflate")
	rr := httptest.NewRecorder()
	app.ServeHTTP(rr, req)

	fmt.Println(rr.Header().Get("Content-Encoding"))
}
Output:
gzip

Index

Examples

Constants

View Source
const DefaultMinLength = 256

DefaultMinLength is the smallest response body (in bytes) that is compressed when no MinLength is configured. Very small payloads are cheaper to send uncompressed.

Variables

This section is empty.

Functions

func New

func New(opts ...Options) express.Handler

New returns middleware that gzip-compresses eligible responses. A response is compressed only when the client's Accept-Encoding includes gzip, the body is at least MinLength bytes, and no Content-Encoding is already set.

Types

type Options

type Options struct {
	// Level is the gzip compression level (gzip.BestSpeed ..
	// gzip.BestCompression). Zero selects gzip.DefaultCompression.
	Level int
	// MinLength is the minimum body size, in bytes, eligible for compression.
	// Zero selects DefaultMinLength.
	MinLength int
}

Options configures the compression middleware.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL