compress

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: May 8, 2025 License: MPL-2.0 Imports: 13 Imported by: 0

README

gin-compress

Middleware for Gin Gonic for compressing HTTP responses and decompressing HTTP requests.

Currently, this package supports Brotli, GZIP, Deflate, and ZSTD for both compressing and decompressing.

This is a fork of the original gin-compress package that adds compression metrics functionality. The original package is currently unmaintained.

Usage

If nothing special is desired, one can add the Compress middleware with the default config to your Gin router like so:

package main


import (
	"log"
	"github.com/gin-gonic/gin"
	limits "github.com/gin-contrib/size"
	"github.com/rdelcampog/compress"
)

func main() {
	r := gin.Default()
	r.Use(compress.Compress())
	// Limit payload to 10 MB, notice how it follows Compress() MW.
	// See the "Security" section below...
	r.Use(limits.RequestSizeLimiter(10 * 1024 * 1024)) 
	
	// Declare routes and do whatever else here...
	
	log.Fatalln(r.Run())
}

Despite the name, the Compress middleware handles compressing both the response body and decompressing the request body.

To configure the middleware, pass the return value of the functions beginning with With to the middleware's constructors, like so:

// disables Brotli
r.Use(compress.Compress(compress.WithAlgo(compress.BROTLI, false)))
Configuration

The following configuration options are available for the Compress middleware:

Function Signature Default Description
WithAlgo(algo string, enable bool) All enabled Allows enabling/disabling any of the supported algorithms. Valid algorithms are currently compress.ZSTD, compress.BROTLI, compress.GZIP, and compress.DEFLATE
WithCompressLevel(algo string, level int) Default for all algorithms Allows setting the compression level for any supported algorithm. See the Brotli*, GzFlate*, and Zstd* constants.
WithPriority(algo string, priority int) Order is Brotli, GZIP, Deflate, ZSTD Specify the priority of an algorithm when the client will accept multiple. Higher priorities win.
WithExcludeFunc(f func(c *gin.Context) bool) Not Set Specify a function to be called to determine if the compressor should run. Note that response headers/body is not available at this point.
WithMinCompressBytes(numBytes int) 512 Do not invoke the compressor unless the response body is at least this many bytes
WithMaxDecodeSteps(steps int) 1 Determines how many rounds of decompression to perform if Content-Encoding includes multiple decompression algorithms.
WithDecompressBody(decompress bool) true Specifies whether the request body should be decompressed at all.
WithMetricsHandler(handler MetricsHandler) Not Set Provides a handler function to collect compression metrics such as original size, compressed size, compression algorithm used, etc.
Security

Bugs/design flaws in the underlying compression algorithm implementations could allow for "zip bombs" that, when decompressed, expand to massive payloads. This results in high resource usage and potentially even denial of service. To mitigate this, applications making use of the request body decompression feature (i.e. WithDecompressBody(true), which is the default), should also use gin-contrib/size (or an equivalent) to limit the size of request bodies.

It is important that any payload size limiter middleware used come after the compress middleware as it will be useless otherwise.

An example of correct usage is shown above.

Tests

Tests cover most functionality in this package. The built-in tests can be run using go test.

License Notice
gin-compress Copyright (C) 2022 Aurora McGinnis
Modifications Copyright (C) 2025 Rubén del Campo

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.

The full terms of the Mozilla Public License 2.0 can also be found in the LICENSE.txt file within this repository.

The author of this package is not associated with the authors of Gin in any way.

Metrics Handler

This fork adds the ability to collect metrics about compression operations. You can use the WithMetricsHandler option to provide a function that will be called after each response with the following data:

// MetricsData contains information about compression metrics
type MetricsData struct {
    // OriginalSize is the size of the original response in bytes
    OriginalSize int
    // CompressedSize is the size of the compressed response in bytes (if compression was applied)
    CompressedSize int
    // CompressionApplied indicates whether compression was applied
    CompressionApplied bool
    // EncodingUsed is the encoding used for compression (empty if not compressed)
    EncodingUsed string
}

Example usage:

r := gin.Default()
r.Use(compress.Compress(
    compress.WithMetricsHandler(func(data compress.MetricsData) {
        // Log or collect metrics
        if data.CompressionApplied {
            log.Printf("Compressed %d bytes to %d bytes using %s (%.2f%% reduction)",
                data.OriginalSize, data.CompressedSize, data.EncodingUsed,
                float64(data.OriginalSize-data.CompressedSize)/float64(data.OriginalSize)*100)
        }
    }),
))

Documentation

Index

Constants

View Source
const (
	BrotliBestSpeed          = brotli.BestSpeed
	BrotliBestCompression    = brotli.BestCompression
	BrotliDefaultCompression = brotli.DefaultCompression
)
View Source
const (
	DEFLATE = "deflate"
	GZIP    = "gzip"
	ZSTD    = "zstd"
	BROTLI  = "br"
)
View Source
const (
	GzFlateDefault             = flate.DefaultCompression
	GzFlateNoCompression       = flate.NoCompression
	GzFlateBestSpeed           = flate.BestSpeed
	GzFlateBestCompression     = flate.BestCompression
	GzFlateConstantCompression = flate.ConstantCompression
	GzFlateHuffmanOnly         = flate.HuffmanOnly
)

GzFlate* constants are suitable for both Deflate and GZIP

View Source
const (
	ZstdSpeedFastest           = int(zstd.SpeedFastest)
	ZstdSpeedDefault           = int(zstd.SpeedDefault)
	ZstdSpeedBetterCompression = int(zstd.SpeedBetterCompression)
	ZstdSpeedBestCompression   = int(zstd.SpeedBestCompression)
)

Variables

This section is empty.

Functions

func Compress

func Compress(opts ...CompressOption) gin.HandlerFunc

Compress creates the Compress middleware with the provided options

Types

type CompressOption

type CompressOption func(opts *compressOptions)

func WithAlgo

func WithAlgo(algo string, enable bool) CompressOption

WithAlgo specifies whether algo should be enabled for both compression and decompression

func WithCompressLevel

func WithCompressLevel(algo string, level int) CompressOption

WithCompressLevel specifies what level to use for compression. Take care that the specified level is valid for the algorithm you've selected.

func WithDecompressBody

func WithDecompressBody(decompress bool) CompressOption

WithDecompressBody specifies whether to decompress the request body

func WithExcludeFunc

func WithExcludeFunc(f func(c *gin.Context) bool) CompressOption

WithExcludeFunc specifies a function that is called before compression to determine if the response to the current request shouldn't be compressed.

func WithMaxDecodeSteps

func WithMaxDecodeSteps(steps int) CompressOption

WithMaxDecodeSteps specifies how many layers of request body compression to undo if multiple.

func WithMetricsHandler

func WithMetricsHandler(handler MetricsHandler) CompressOption

WithMetricsHandler specifies a handler function that will be called after a response is written with compression metrics data

func WithMinCompressBytes

func WithMinCompressBytes(numBytes int) CompressOption

WithMinCompressBytes specifies the minimum size a response must be before compressing. Using a value <= 0 will always compress.

func WithPriority

func WithPriority(algo string, priority int) CompressOption

WithPriority specifies which compression algo to use when the client can accept multiple algorithms. The highest priority algorithm that the client can accept wins.

type ExcludeFunc

type ExcludeFunc func(c *gin.Context) bool

ExcludeFunc should return true if compression should be skipped for the current request

type MetricsData

type MetricsData struct {
	// OriginalSize is the size of the original response in bytes
	OriginalSize int
	// CompressedSize is the size of the compressed response in bytes (if compression was applied)
	CompressedSize int
	// CompressionApplied indicates whether compression was applied
	CompressionApplied bool
	// EncodingUsed is the encoding used for compression (empty if not compressed)
	EncodingUsed string
}

MetricsData contains information about compression metrics

type MetricsHandler

type MetricsHandler func(data MetricsData)

MetricsHandler is a function that will be called after a response is written to collect compression metrics

Jump to

Keyboard shortcuts

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