Skip to content

Commit 507de02

Browse files
authored
docs : add streaming gzip (#829)
1 parent fe54c49 commit 507de02

File tree

2 files changed

+177
-4
lines changed
  • content
    • en/docs/hertz/tutorials/basic-feature/middleware
    • zh/docs/hertz/tutorials/basic-feature/middleware

2 files changed

+177
-4
lines changed

content/en/docs/hertz/tutorials/basic-feature/middleware/gzip.md

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: "Gzip Compress"
3-
date: 2022-09-25
3+
date: 2022-10-19
44
weight: 4
55
keywords: ["Gzip", "Compress"]
66
description: "Hertz provides an implementation of Gzip."
@@ -17,6 +17,8 @@ go get github.com/hertz-contrib/gzip
1717

1818
## Example
1919

20+
### Gzip
21+
2022
```go
2123
package main
2224

@@ -41,9 +43,94 @@ func main() {
4143
}
4244
```
4345

46+
### Gzip Stream
47+
48+
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.
49+
50+
> 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.
51+
52+
```go
53+
package main
54+
55+
import (
56+
"context"
57+
"fmt"
58+
"io/ioutil"
59+
"strings"
60+
"time"
61+
62+
"github.com/cloudwego/hertz/pkg/app"
63+
"github.com/cloudwego/hertz/pkg/app/client"
64+
"github.com/cloudwego/hertz/pkg/app/server"
65+
"github.com/cloudwego/hertz/pkg/common/compress"
66+
"github.com/cloudwego/hertz/pkg/protocol"
67+
"github.com/cloudwego/hertz/pkg/protocol/consts"
68+
"github.com/hertz-contrib/gzip"
69+
)
70+
71+
func main() {
72+
h := server.Default(server.WithHostPorts(":8081"))
73+
74+
// Note: Using this middleware will hijack the response writer and may have an impact on other interfaces.
75+
// Therefore, it is only necessary to use this middleware on interfaces with streaming gzip requirements.
76+
h.GET("/ping", gzip.GzipStream(gzip.DefaultCompression), func(ctx context.Context, c *app.RequestContext) {
77+
for i := 0; i < 10; i++ {
78+
c.Write([]byte(fmt.Sprintf("chunk %d: %s\n", i, strings.Repeat("hi~", i)))) // nolint: errcheck
79+
c.Flush() // nolint: errcheck
80+
time.Sleep(time.Second)
81+
}
82+
})
83+
go h.Spin()
84+
85+
cli, err := client.NewClient(client.WithResponseBodyStream(true))
86+
if err != nil {
87+
panic(err)
88+
}
89+
90+
req := protocol.AcquireRequest()
91+
res := protocol.AcquireResponse()
92+
93+
req.SetMethod(consts.MethodGet)
94+
req.SetRequestURI("http://localhost:8081/ping")
95+
req.Header.Set("Accept-Encoding", "gzip")
96+
97+
if err = cli.Do(context.Background(), req, res); err != nil {
98+
panic(err)
99+
}
100+
101+
bodyStream := res.BodyStream()
102+
103+
r, err := compress.AcquireGzipReader(bodyStream)
104+
if err != nil {
105+
panic(err)
106+
}
107+
108+
firstChunk := make([]byte, 10)
109+
_, err = r.Read(firstChunk)
110+
if err != nil {
111+
panic(err)
112+
}
113+
fmt.Println(fmt.Printf("%s", firstChunk))
114+
115+
secondChunk := make([]byte, 13)
116+
_, err = r.Read(secondChunk)
117+
if err != nil {
118+
panic(err)
119+
}
120+
fmt.Println(fmt.Printf("%s", secondChunk))
121+
122+
otherChunks, _ := ioutil.ReadAll(r)
123+
fmt.Println(fmt.Printf("%s", otherChunks))
124+
125+
if r != nil {
126+
compress.ReleaseGzipReader(r)
127+
}
128+
}
129+
```
130+
44131
## Config
45132

46-
### Gzip
133+
> The following configuration is also applicable to `Gzip Stream`.
47134
48135
`Gzip` provides four compression options: `BestCompression`, `BestSpeed`, `DefaultCompression`, `NoCompression` for user-defined compression modes
49136

content/zh/docs/hertz/tutorials/basic-feature/middleware/gzip.md

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22

33
title: "Gzip 压缩"
4-
date: 2022-09-01
4+
date: 2022-10-19
55
weight: 4
66
keywords: ["Gzip", "压缩"]
77
description: "Hertz 提供了 Gzip 的实现。"
@@ -18,6 +18,8 @@ go get github.com/hertz-contrib/gzip
1818

1919
## 示例代码
2020

21+
### Gzip
22+
2123
```go
2224
package main
2325

@@ -40,12 +42,96 @@ func main() {
4042
})
4143
h.Spin()
4244
}
45+
```
46+
47+
### GzipStream
48+
49+
若用户有 gzip 压缩加 chunk 流式写的需求,可以使用该中间件。该中间件的行为是:将每个 chunk 分块先 gzip 压缩再发送给客户端。每个 chunk 分块都是一份独立的压缩数据,所以客户端收到的每个 chunk 分块都可以独立解压使用。
50+
51+
> 注意:使用该中间件会劫持 response writer,可能会对其他接口造成影响,因此,只需要在有流式 gzip 需求的接口使用该中间件。
4352
53+
```go
54+
package main
55+
56+
import (
57+
"context"
58+
"fmt"
59+
"io/ioutil"
60+
"strings"
61+
"time"
62+
63+
"github.com/cloudwego/hertz/pkg/app"
64+
"github.com/cloudwego/hertz/pkg/app/client"
65+
"github.com/cloudwego/hertz/pkg/app/server"
66+
"github.com/cloudwego/hertz/pkg/common/compress"
67+
"github.com/cloudwego/hertz/pkg/protocol"
68+
"github.com/cloudwego/hertz/pkg/protocol/consts"
69+
"github.com/hertz-contrib/gzip"
70+
)
71+
72+
func main() {
73+
h := server.Default(server.WithHostPorts(":8081"))
74+
75+
// Note: Using this middleware will hijack the response writer and may have an impact on other interfaces.
76+
// Therefore, it is only necessary to use this middleware on interfaces with streaming gzip requirements.
77+
h.GET("/ping", gzip.GzipStream(gzip.DefaultCompression), func(ctx context.Context, c *app.RequestContext) {
78+
for i := 0; i < 10; i++ {
79+
c.Write([]byte(fmt.Sprintf("chunk %d: %s\n", i, strings.Repeat("hi~", i)))) // nolint: errcheck
80+
c.Flush() // nolint: errcheck
81+
time.Sleep(time.Second)
82+
}
83+
})
84+
go h.Spin()
85+
86+
cli, err := client.NewClient(client.WithResponseBodyStream(true))
87+
if err != nil {
88+
panic(err)
89+
}
90+
91+
req := protocol.AcquireRequest()
92+
res := protocol.AcquireResponse()
93+
94+
req.SetMethod(consts.MethodGet)
95+
req.SetRequestURI("http://localhost:8081/ping")
96+
req.Header.Set("Accept-Encoding", "gzip")
97+
98+
if err = cli.Do(context.Background(), req, res); err != nil {
99+
panic(err)
100+
}
101+
102+
bodyStream := res.BodyStream()
103+
104+
r, err := compress.AcquireGzipReader(bodyStream)
105+
if err != nil {
106+
panic(err)
107+
}
108+
109+
firstChunk := make([]byte, 10)
110+
_, err = r.Read(firstChunk)
111+
if err != nil {
112+
panic(err)
113+
}
114+
fmt.Println(fmt.Printf("%s", firstChunk))
115+
116+
secondChunk := make([]byte, 13)
117+
_, err = r.Read(secondChunk)
118+
if err != nil {
119+
panic(err)
120+
}
121+
fmt.Println(fmt.Printf("%s", secondChunk))
122+
123+
otherChunks, _ := ioutil.ReadAll(r)
124+
fmt.Println(fmt.Printf("%s", otherChunks))
125+
126+
if r != nil {
127+
compress.ReleaseGzipReader(r)
128+
}
129+
}
44130
```
45131

46132
## 配置
47133

48-
### Gzip
134+
> 以下配置对 `GzipStream` 同样适用。
49135
50136
`Gzip`提供了四种压缩选项:`BestCompression`,`BestSpeed`,`DefaultCompression`,`NoCompression` 用于用户自定义压缩模式
51137

0 commit comments

Comments
 (0)