Gzip Compress
In HTTP, GNUzip(Gzip) compression coding is a way to optimize the performance of Web applications, and Hertz also provides an implementation of Gzip.
Install
go get github.com/hertz-contrib/gzip
Example
Gzip
package main
import (
"context"
"fmt"
"net/http"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/hertz-contrib/gzip"
)
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.Use(gzip.Gzip(gzip.DefaultCompression))
h.GET("/ping", func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
})
h.Spin()
}
Gzip Stream
If the user has a need for gzip compression combined with chunked streaming writing, they can use this middleware. The behavior of this middleware is to chunk each chunk, compress it with gzip, and then send it to the client. Each chunk is a separate compressed data, so each chunk received by the client can be independently decompressed and used.
Note: Using this middleware will hijack the response writer and may have an impact on other interfaces. Therefore, it is only necessary to use this middleware on interfaces with streaming gzip requirements.
package main
import (
"context"
"fmt"
"io/ioutil"
"strings"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/client"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/compress"
"github.com/cloudwego/hertz/pkg/protocol"
"github.com/cloudwego/hertz/pkg/protocol/consts"
"github.com/hertz-contrib/gzip"
)
func main() {
h := server.Default(server.WithHostPorts(":8081"))
// Note: Using this middleware will hijack the response writer and may have an impact on other interfaces.
// Therefore, it is only necessary to use this middleware on interfaces with streaming gzip requirements.
h.GET("/ping", gzip.GzipStream(gzip.DefaultCompression), func(ctx context.Context, c *app.RequestContext) {
for i := 0; i < 10; i++ {
c.Write([]byte(fmt.Sprintf("chunk %d: %s\n", i, strings.Repeat("hi~", i)))) // nolint: errcheck
c.Flush() // nolint: errcheck
time.Sleep(time.Second)
}
})
go h.Spin()
cli, err := client.NewClient(client.WithResponseBodyStream(true))
if err != nil {
panic(err)
}
req := protocol.AcquireRequest()
res := protocol.AcquireResponse()
req.SetMethod(consts.MethodGet)
req.SetRequestURI("http://localhost:8081/ping")
req.Header.Set("Accept-Encoding", "gzip")
if err = cli.Do(context.Background(), req, res); err != nil {
panic(err)
}
bodyStream := res.BodyStream()
r, err := compress.AcquireGzipReader(bodyStream)
if err != nil {
panic(err)
}
firstChunk := make([]byte, 10)
_, err = r.Read(firstChunk)
if err != nil {
panic(err)
}
fmt.Println(fmt.Printf("%s", firstChunk))
secondChunk := make([]byte, 13)
_, err = r.Read(secondChunk)
if err != nil {
panic(err)
}
fmt.Println(fmt.Printf("%s", secondChunk))
otherChunks, _ := ioutil.ReadAll(r)
fmt.Println(fmt.Printf("%s", otherChunks))
if r != nil {
compress.ReleaseGzipReader(r)
}
}
Config
The following configuration is also applicable to
Gzip Stream
.
Gzip
provides four compression options: BestCompression
, BestSpeed
, DefaultCompression
, NoCompression
for user-defined compression modes
Options | Description |
---|---|
BestCompression | Provides the best file compression ratio |
BestSpeed | Provides the best compression speed |
DefaultCompression | Default compression rate |
NoCompression | No compression |
Function Signature:
func Gzip(level int, options ...Option) app.HandlerFunc
Sample Code:
package main
import (
"context"
"fmt"
"net/http"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/hertz-contrib/gzip"
)
func main() {
h := server.Default(server.WithHostPorts(":8080"))
// BestCompression option
h.Use(gzip.Gzip(gzip.BestCompression))
// BestSpeed option
h.Use(gzip.Gzip(gzip.BestSpeed))
// DefaultCompression option
h.Use(gzip.Gzip(gzip.DefaultCompression))
// NoCompression option
h.Use(gzip.Gzip(gzip.NoCompression))
h.GET("/api/book", func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
})
h.Spin()
}
WithExcludedExtensions
gzip
provides WithExcludeExtensions
to help users set file extensions that do not require gzip
compression, the default values are .png
, .gif
, .jpeg
, .jpg
Function Signature:
func WithExcludedPaths(args []string) Option
Sample Code:
package main
import (
"context"
"fmt"
"net/http"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/hertz-contrib/gzip"
)
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.Use(
gzip.Gzip(
gzip.DefaultCompression,
gzip.WithExcludedExtensions([]string{".pdf", ".mp4"}),
),
)
h.GET("/api/book", func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
})
h.Spin()
}
WithExcludedPaths
gzip
provides WithExcludedPaths
to help users set the paths of files they do not want to compress with gzip
Function Signature:
func WithExcludedPaths(args []string) Option
Sample Code:
package main
import (
"context"
"fmt"
"net/http"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/hertz-contrib/gzip"
)
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.Use(
gzip.Gzip(
gzip.DefaultCompression,
// This WithExcludedPaths takes as its parameter the file path
gzip.WithExcludedPaths([]string{"/api/"}),
),
)
// This is No compression
h.GET("/api/book", func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
})
// This is the compressed
h.GET("/book", func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
})
h.Spin()
}
WithExcludedPathRegexes
gzip
provides WithExcludedPathRegexes
to help users set custom regular expressions to filter out files that do not need to be compressed by gzip
Function Signature
func WithExcludedPathRegexes(args []string) Option
Sample Code:
package main
import (
"context"
"fmt"
"net/http"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/hertz-contrib/gzip"
)
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.Use(
gzip.Gzip(
gzip.DefaultCompression,
// This WithExcludedPathRegexes takes as an argument a regular expression that describes the path to be excluded
gzip.WithExcludedPathRegexes([]string{"/api.*"}),
),
)
// This is No compression
h.GET("/api/book", func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
})
// This is the compressed
h.GET("/book", func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
})
h.Spin()
}
Refer to the gzip for more usage examples