gzip

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Dec 12, 2019 License: MIT Imports: 10 Imported by: 9

README

English | 中文

gzip

GoDoc Build status codecov Lint status Go Report Card

Content-Type and Content-Length aware gzip middleware for Gin and net/http.

Examples

Gin

import github.com/nanmu42/gzip

func main() {
	g := gin.Default()

    // use default settings
	g.Use(gzip.DefaultHandler().Gin)

	g.GET("/", func(c *gin.Context) {
		c.JSON(http.StatusOK, map[string]interface{}{
			"code": 0,
			"msg":  "hello",
			"data": fmt.Sprintf("l%sng!", strings.Repeat("o", 1000)),
		})
	})

	log.Println(g.Run(fmt.Sprintf(":%d", 3000)))
}

net/http

import github.com/nanmu42/gzip

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		writeString(w, fmt.Sprintf("This content is compressed: l%sng!", strings.Repeat("o", 1000)))
	})

    // wrap http.Handler using default settings
	log.Println(http.ListenAndServe(fmt.Sprintf(":%d", 3001), gzip.DefaultHandler().WrapHandler(mux)))
}

func writeString(w http.ResponseWriter, payload string) {
	w.Header().Set("Content-Type", "text/plain; charset=utf8")
	_, _ = io.WriteString(w, payload+"\n")
}

Customize Handler

Handler can be customized during initialization:

import github.com/nanmu42/gzip

handler := gzip.NewHandler(gzip.Config{
    // gzip compression level to use
	CompressionLevel: 6,
    // minimum content length to trigger gzip, the unit is in byte.
	MinContentLength: 256,
    // RequestFilter decide whether or not to compress response judging by request.
    // Filters are applied in the sequence here.
	RequestFilter: []RequestFilter{
	    NewCommonRequestFilter(),
	    DefaultExtensionFilter(),
	},
    // ResponseHeaderFilter decide whether or not to compress response
    // judging by request
	ResponseHeaderFilter: []ResponseHeaderFilter{
		NewSkipCompressedFilter(),
		DefaultContentTypeFilter(),
	},
})

RequestFilter and ResponseHeaderFilter are interfaces. You may define one that specially suits your need.

Limitation

  • You should always provide a Content-Type in http response's header, as handler does not guess;
  • handler looks up Content-Length in http response's header firstly, falls back to len(data) of the first http.ResponseWriter.Write(data []byte) calling. It may not use gzip if Content-Length is absent and len(data) is low.

If you are using Gin's c.JSON() or c.PureJSON(), you are safe from above limitation, as Gin sets proper Content-Type and write response in full length.

If you are using net/http, make sure above cases are considered.

Status: v0

API not stabilized, things may breaks.

You are welcome to try gzip on your test/unimportant environments.

Pull requests and issues are welcome.

Acknowledgement

During the development of this work, the author took following works/materials as reference:

License

MIT License
Copyright (c) 2019 LI Zhennan

Caddy is licensed under the Apache License
Copyright 2015 Light Code Labs, LLC

Documentation

Overview

Package gzip implements gzip middleware for Gin and net/http.

* introduction: https://github.com/nanmu42/gzip

* examples: https://github.com/nanmu42/gzip/tree/master/examples

Index

Constants

View Source
const (
	NoCompression      = gzip.NoCompression
	BestSpeed          = gzip.BestSpeed
	BestCompression    = gzip.BestCompression
	DefaultCompression = gzip.DefaultCompression
	HuffmanOnly        = gzip.HuffmanOnly
)

These constants are copied from the gzip package

Variables

This section is empty.

Functions

This section is empty.

Types

type CommonRequestFilter

type CommonRequestFilter struct{}

CommonRequestFilter judge via common easy criteria like http method, accept-encoding header, etc.

func NewCommonRequestFilter

func NewCommonRequestFilter() *CommonRequestFilter

NewCommonRequestFilter ...

func (*CommonRequestFilter) ShouldCompress

func (c *CommonRequestFilter) ShouldCompress(req *http.Request) bool

ShouldCompress implements RequestFilter interface

type Config

type Config struct {
	// gzip compression level to use,
	// valid value: -2 ~ 9.
	//
	// see https://golang.org/pkg/compress/gzip/#NewWriterLevel
	CompressionLevel int
	// Minimum content length to trigger gzip,
	// the unit is in byte.
	//
	// Content length is obtained in response's header,
	// and len(data) of http.ResponseWriter.Write(data []byte)'s first calling
	// if header["Content-Length"] is not available.
	MinContentLength int64
	// Filters are applied in the sequence here
	RequestFilter []RequestFilter
	// Filters are applied in the sequence here
	ResponseHeaderFilter []ResponseHeaderFilter
}

Config is used in Handler initialization

type ContentTypeFilter

type ContentTypeFilter struct {
	Types      *acascii.Matcher
	AllowEmpty bool
}

ContentTypeFilter judge via the response content type

Omit this filter if you want to compress all content type.

func DefaultContentTypeFilter

func DefaultContentTypeFilter() *ContentTypeFilter

DefaultContentTypeFilter permits

func NewContentTypeFilter

func NewContentTypeFilter(types []string) *ContentTypeFilter

NewContentTypeFilter ...

func (*ContentTypeFilter) ShouldCompress

func (e *ContentTypeFilter) ShouldCompress(header http.Header) bool

ShouldCompress implements RequestFilter interface

type ExtensionFilter

type ExtensionFilter struct {
	Exts       *acascii.Matcher
	AllowEmpty bool
}

ExtensionFilter judge via the extension in path

Omit this filter if you want to compress all extension.

func DefaultExtensionFilter

func DefaultExtensionFilter() *ExtensionFilter

DefaultExtensionFilter permits

func NewExtensionFilter

func NewExtensionFilter(extensions []string) *ExtensionFilter

NewExtensionFilter returns a extension or panics

func (*ExtensionFilter) ShouldCompress

func (e *ExtensionFilter) ShouldCompress(req *http.Request) bool

ShouldCompress implements RequestFilter interface

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler implement gzip compression for gin and net/http

func DefaultHandler

func DefaultHandler() *Handler

DefaultHandler creates a gzip handler to take care of response compression, with meaningful preset.

func NewHandler

func NewHandler(config Config) *Handler

NewHandler initialized a costumed gzip handler to take care of response compression.

config must not be modified after calling on NewHandler()

func (*Handler) Gin

func (h *Handler) Gin(c *gin.Context)

Gin implement gin's middleware

func (*Handler) WrapHandler

func (h *Handler) WrapHandler(next http.Handler) http.Handler

WrapHandler wraps a http.Handler, returning its gzip-enabled version

type RequestFilter

type RequestFilter interface {
	// ShouldCompress decide whether or not to compress response,
	// judging by request
	ShouldCompress(req *http.Request) bool
}

RequestFilter decide whether or not to compress response judging by request

type ResponseHeaderFilter

type ResponseHeaderFilter interface {
	// ShouldCompress decide whether or not to compress response,
	// judging by response header
	ShouldCompress(header http.Header) bool
}

ResponseHeaderFilter decide whether or not to compress response judging by response header

type SkipCompressedFilter

type SkipCompressedFilter struct{}

SkipCompressedFilter judges whether content has been already compressed

func NewSkipCompressedFilter

func NewSkipCompressedFilter() *SkipCompressedFilter

NewSkipCompressedFilter ...

func (*SkipCompressedFilter) ShouldCompress

func (s *SkipCompressedFilter) ShouldCompress(header http.Header) bool

ShouldCompress implements ResponseHeaderFilter interface

Content-Encoding: https://tools.ietf.org/html/rfc2616#section-3.5

Directories

Path Synopsis
examples
gin

Jump to

Keyboard shortcuts

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