Skip to content

Commit b2210e3

Browse files
committed
docs: add doc for hertz v0.10.0
1 parent ff86ac9 commit b2210e3

6 files changed

Lines changed: 373 additions & 0 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
title: "Hertz Release v0.10.0"
3+
linkTitle: "Release v0.10.0"
4+
projects: ["Hertz"]
5+
date: 2025-05-21
6+
description: >
7+
---
8+
9+
The Hertz v0.10.0 release adds two features and some fixes.
10+
11+
1. Integrate SSE functionality. Refer to [SSE](/docs/hertz/tutorials/basic-feature/sse) for usage.
12+
2. Added http.Handler adaptor, extending Hertz using the official net/http ecosystem. Refer to [Adaptor](/docs/hertz/tutorials/basic-feature/http-adaptor) for usage.
13+
14+
## Feature
15+
1. [[#1327](https://github.com/cloudwego/hertz/pull/1327)] feat(adaptor): new HertzHandler for http.Handler
16+
2. [[#1349](https://github.com/cloudwego/hertz/pull/1349)] feat(sse): SetLastEventID
17+
3. [[#1343](https://github.com/cloudwego/hertz/pull/1343)] feat(sse): reader supports cancel stream
18+
4. [[#1341](https://github.com/cloudwego/hertz/pull/1341)] feat(server): detect request race
19+
5. [[#1339](https://github.com/cloudwego/hertz/pull/1339)] feat(sse): add LastEventID helpers
20+
6. [[#1335](https://github.com/cloudwego/hertz/pull/1335)] feat(protocol): new sse pkg
21+
7. [[#1322](https://github.com/cloudwego/hertz/pull/1322)] feat: std transport sense client connection close
22+
23+
## Fix
24+
1. [[#1340](https://github.com/cloudwego/hertz/pull/1340)] fix: only use netpoll & sonic on amd64/arm64 linux/darwin
25+
2. [[#1333](https://github.com/cloudwego/hertz/pull/1333)] fix(protocol): unexpected set resp.bodyStream
26+
3. [[#1329](https://github.com/cloudwego/hertz/pull/1329)] fix(client): stream body for sse instead of timeout
27+
4. [[#1332](https://github.com/cloudwego/hertz/pull/1332)] fix(server): Shutdown checks ExitWaitTimeout
28+
5. [[#1316](https://github.com/cloudwego/hertz/pull/1316)] fix: prioritize custom validator
29+
30+
## Tests
31+
1. [[#1336](https://github.com/cloudwego/hertz/pull/1336)] test(protocol): fix hardcoded listen addr
32+
33+
## Chore
34+
1. [[#1353](https://github.com/cloudwego/hertz/pull/1353)] chore: update netpoll dependency
35+
2. [[#1337](https://github.com/cloudwego/hertz/pull/1337)] chore(hz): update hz tool v0.9.7
36+
3. [[#1328](https://github.com/cloudwego/hertz/pull/1328)] ci: disable codecov annotations
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: "Hertz http.Handler adaptor"
3+
date: 2025-05-21
4+
weight: 12
5+
keywords: ["adaptor"]
6+
description: "Hertz http.Handler adaptor"
7+
---
8+
9+
## Background
10+
- We will deprecate the Hertz's native file system
11+
- Provide an fs implementation that is both compatible and performs well, using the official net/http ecosystem.
12+
- Reduce the implementation of a large number of extensions by expanding the hertz function through the official net/http ecosystem
13+
14+
## What is adaptor.HertzHandler
15+
- You are allowed to directly convert your existing http.HandlerFunc method into a HertzHandler.
16+
- You can directly use http.FileServer, embed.FS, and other official ecosystems
17+
- You can even use this directly at Hertz github.com/gorilla/websocket
18+
19+
## Example
20+
```go
21+
package main
22+
23+
import (
24+
"embed"
25+
"net/http"
26+
27+
"github.com/cloudwego/hertz/pkg/app/server"
28+
"github.com/cloudwego/hertz/pkg/common/adaptor"
29+
)
30+
31+
//go:embed static/*
32+
var staticFiles embed.FS
33+
34+
func main() {
35+
h := server.Default()
36+
37+
helloHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
38+
w.Write([]byte("Hello hertz!"))
39+
})
40+
h.GET("/hello", adaptor.HertzHandler(helloHandler))
41+
42+
staticFS := adaptor.HertzHandler(http.FileServer(http.FS(staticFiles)))
43+
h.GET("/static/*filepath", staticFS)
44+
h.HEAD("/static/*filepath", staticFS)
45+
h.Spin()
46+
}
47+
```
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
title: "SSE"
3+
date: 2025-05-21
4+
weight: 12
5+
keywords: ["SSE"]
6+
description: "Hertz Support SSE。"
7+
---
8+
```Code:https://github.com/cloudwego/hertz/tree/develop/pkg/protocol/sse```
9+
10+
**Changelog**
11+
- 2025/05/15 Has been released to the open-source version v0.10.0
12+
- 2025/05/13 [d3c68463] Added Get / SetLastEventID.
13+
- 2025/05/13 [3952e956] The Reader ForEach interface supports passing in ctx.
14+
- 2025/04/24 [cf38573ce] First version completed
15+
16+
## 什么是Server-Sent Events (SSE)
17+
- SSE is an HTML standard used to describe the implementation of the EventSource API in browsers. Strictly speaking, it is not an HTTP protocol.
18+
- Both the popular Model Context Protocol (MCP) and Agent2Agent (A2A) protocols are based to some extent on SSE
19+
- https://www.anthropic.com/news/model-context-protocol
20+
- https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
21+
22+
## Server Implementation
23+
### Return data
24+
```go
25+
import "github.com/cloudwego/hertz/pkg/protocol/sse"
26+
27+
func HandleSSE(ctx context.Context, c *app.RequestContext) {
28+
println("Server Got LastEventID", sse.GetLastEventID(&c.Request))
29+
w := sse.NewWriter(c)
30+
for i := 0; i < 5; i++ {
31+
w.WriteEvent("id-x", "message", []byte("hello\n\nworld"))
32+
time.Sleep(10 * time.Millisecond)
33+
}
34+
w.Close() // 发送最后的chunk数据,确保优雅退出。可选,Hertz 在 Handler 返回后会自动调用。
35+
36+
// 请确保 writer 的生命周期和handler一致。不要go异步后台使用。
37+
}
38+
```
39+
40+
41+
### FAQ
42+
#### connection has been closed when flush
43+
Reason: The client connection has been disconnected, possibly due to a long time without response data. Please check the corresponding configuration.
44+
45+
46+
## Client Implementation
47+
48+
### Initiate a request
49+
It's exactly the same as making a normal HTTP request to Hertz.
50+
Note: The new Hertz version will automatically recognize SSE streams, so you don't need to explicitly set `WithResponseBodyStream(true)`
51+
52+
**Some optional headers**
53+
```go
54+
import "github.com/cloudwego/hertz/pkg/protocol/sse"
55+
56+
sse.AddAcceptMIME(req) // 部分SSE Server可能会要求显式增加 Accept: text/event-stream
57+
sse.SetLastEventID(req, "id-123") // 对于有状态服务,需要通过 SetLastEventID 告诉 Server
58+
```
59+
60+
### Handle response
61+
```go
62+
import "github.com/cloudwego/hertz/pkg/protocol/sse"
63+
64+
func HandleSSE(ctx context.Context, resp *protocol.Response) error {
65+
r, err := sse.NewReader(resp)
66+
if err != nil {
67+
return err
68+
}
69+
70+
// 也可以手动调用 r.Read 方法
71+
err = r.ForEach(ctx, func(e *Event) error {
72+
println("Event:", e.String())
73+
return nil
74+
})
75+
if err != nil { // 如果 Server 正常断开,这里 err == nil,不会报错
76+
// 其他io错误 或 ctx cancelled
77+
return err
78+
}
79+
println("Client LastEventID", r.LastEventID()) // 可用于保存最后接收的 Event ID
80+
return nil
81+
}
82+
```
83+
84+
### FAQ
85+
86+
#### How to implement multi-level SSE/SSE Proxy?
87+
- You can refer to the implementations on both the Client and Server sides simultaneously
88+
- Enable `WithSenseClientDisconnection` in the server and pass the context to the next hop's Reader ForEach
89+
- In this way, when the Client disconnects, it will be automatically recognized, and the entire stream will be interrupted
90+
91+
## Event Struct
92+
```go
93+
// Event represents a Server-Sent Event (SSE).
94+
type Event struct {
95+
ID string // 即 Event ID,sse.Reader 会自动记录最后的 Event ID,可使用 LastEventID() 获取
96+
Type string // 即 Event Type,常见的如 "message"
97+
Data []byte // 为了方便使用 Unmarshal/Marshal,这里使用 []byte,但是按spec这个字段必须要 utf8 string
98+
99+
// 不建议使用,主要是针对浏览器的 SourceEvent 返回该字段控制其重试策略。
100+
// 如果使用Hertz作为Client可以参考:https://www.cloudwego.io/docs/hertz/tutorials/basic-feature/retry/
101+
Retry time.Duration
102+
}
103+
```
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
title: "Hertz Release v0.10.0"
3+
linkTitle: "Release v0.10.0"
4+
projects: ["Hertz"]
5+
date: 2025-05-21
6+
description: >
7+
---
8+
9+
Hertz v0.10.0 版本新增两项功能并修复了一些问题。
10+
11+
1. 集成 SSE 功能。使用方法请参阅 [SSE](/docs/hertz/tutorials/basic-feature/sse)
12+
2. 添加 http.Handler 适配器,使用官方 net/http 生态系统扩展 Hertz。使用方法请参阅 [Adaptor](/docs/hertz/tutorials/basic-feature/http-adaptor)
13+
14+
## Feature
15+
1. [[#1327](https://github.com/cloudwego/hertz/pull/1327)] feat(adaptor): 为 http.Handler 添加新的 HertzHandler
16+
2. [[#1349](https://github.com/cloudwego/hertz/pull/1349)] feat(sse): SetLastEventID
17+
3. [[#1343](https://github.com/cloudwego/hertz/pull/1343)] feat(sse): reader 支持取消流
18+
4. [[#1341](https://github.com/cloudwego/hertz/pull/1341)] feat(server): 检测请求 race
19+
5. [[#1339](https://github.com/cloudwego/hertz/pull/1339)] feat(sse): 添加 LastEventID helper
20+
6. [[#1335](https://github.com/cloudwego/hertz/pull/1335)] feat(protocol): 新的 sse 包
21+
7. [[#1322](https://github.com/cloudwego/hertz/pull/1322)] feat: server 使用标准 go net 传输时感知客户端连接关闭
22+
23+
## Fix
24+
1. [[#1340](https://github.com/cloudwego/hertz/pull/1340)] fix:仅在 amd64/arm64 linux/darwin 上使用 netpoll 和 sonic
25+
2. [[#1333](https://github.com/cloudwego/hertz/pull/1333)] fix(protocol): 非预期的设置 resp.bodyStream
26+
3. [[#1329](https://github.com/cloudwego/hertz/pull/1329)] fix(client): sse 场景下自动切换为 stream body 模式
27+
4. [[#1332](https://github.com/cloudwego/hertz/pull/1332)] fix(server): server 关闭时检查 ExitWaitTimeout
28+
5. [[#1316](https://github.com/cloudwego/hertz/pull/1316)] fix: 优先使用自定义 validator
29+
30+
## Tests
31+
1. [[#1336](https://github.com/cloudwego/hertz/pull/1336)] test(protocol): 修复硬编码的监听地址
32+
33+
## Chore
34+
1. [[#1353](https://github.com/cloudwego/hertz/pull/1353)] chore:更新 netpoll 依赖
35+
2. [[#1337](https://github.com/cloudwego/hertz/pull/1337)] chore(hz): 更新 hz 工具 v0.9.7
36+
3. [[#1328](https://github.com/cloudwego/hertz/pull/1328)] ci: 禁用 codecov 注释
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: "Hertz http.Handler adaptor"
3+
date: 2025-05-21
4+
weight: 12
5+
keywords: ["adaptor"]
6+
description: "Hertz http.Handler adaptor"
7+
---
8+
9+
## 背景
10+
- 主淘汰长期没有良好维护的 hertz 原生 fs 实现;
11+
- 通过官方 net/http 生态提供一个兼容性较好,性能也不差的 fs 实现。
12+
- 通过官方 net/http 生态扩展 hertz 功能,减少大量扩展实现
13+
14+
## 什么是 adaptor.HertzHandler
15+
- 允许你将现有的 http.HandlerFunc 方法直接转为 HertzHandler
16+
- 可以直接使用 http.FileServer embed.FS 等官方生态
17+
- 甚至可以直接在 Hertz 使用 github.com/gorilla/websocket
18+
19+
## 具体例子
20+
```go
21+
package main
22+
23+
import (
24+
"embed"
25+
"net/http"
26+
27+
"github.com/cloudwego/hertz/pkg/app/server"
28+
"github.com/cloudwego/hertz/pkg/common/adaptor"
29+
)
30+
31+
//go:embed static/*
32+
var staticFiles embed.FS
33+
34+
func main() {
35+
h := server.Default()
36+
37+
helloHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
38+
w.Write([]byte("Hello hertz!"))
39+
})
40+
h.GET("/hello", adaptor.HertzHandler(helloHandler))
41+
42+
staticFS := adaptor.HertzHandler(http.FileServer(http.FS(staticFiles)))
43+
h.GET("/static/*filepath", staticFS)
44+
h.HEAD("/static/*filepath", staticFS)
45+
h.Spin()
46+
}
47+
```
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
---
2+
title: "SSE"
3+
date: 2025-05-21
4+
weight: 12
5+
keywords: ["SSE"]
6+
description: "Hertz 提供的 SSE 能力。"
7+
---
8+
```代码:https://github.com/cloudwego/hertz/tree/develop/pkg/protocol/sse```
9+
10+
**Changelog**
11+
- 2025/05/15 已发布到开源版本 v0.10.0
12+
- 2025/05/13 [d3c68463] 增加 Get / SetLastEventID
13+
- 2025/05/13 [3952e956] Reader ForEach 接口支持传入 ctx
14+
- 2025/04/24 [cf38573ce] 第一版本完成
15+
16+
## 什么是Server-Sent Events (SSE)
17+
- SSE是一个HTML标准,用于描述浏览器 EventSource API 的实现。严格说,不是http协议。
18+
- 流行的 Model Context Protocol (MCP) 或 Agent2Agent (A2A) 协议都一定程度基于 SSE
19+
- https://www.anthropic.com/news/model-context-protocol
20+
- https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
21+
22+
## Server端实现
23+
### 返回数据
24+
```go
25+
import "github.com/cloudwego/hertz/pkg/protocol/sse"
26+
27+
func HandleSSE(ctx context.Context, c *app.RequestContext) {
28+
println("Server Got LastEventID", sse.GetLastEventID(&c.Request))
29+
w := sse.NewWriter(c)
30+
for i := 0; i < 5; i++ {
31+
w.WriteEvent("id-x", "message", []byte("hello\n\nworld"))
32+
time.Sleep(10 * time.Millisecond)
33+
}
34+
w.Close() // 发送最后的chunk数据,确保优雅退出。可选,Hertz 在 Handler 返回后会自动调用。
35+
36+
// 请确保 writer 的生命周期和handler一致。不要go异步后台使用。
37+
}
38+
```
39+
40+
41+
### 常见问题
42+
#### connection has been closed when flush
43+
原因:
44+
Client连接断开,可能是太久没有响应数据,请检查相应配置。
45+
46+
47+
## Client端实现
48+
49+
### 发起请求
50+
与正常 Hertz 发起一个普通的http请求完全一致。
51+
注意:新hertz版本会自动识别SSE流,不用显式设置 WithResponseBodyStream(true)
52+
53+
**部分可选 Header**
54+
```go
55+
import "github.com/cloudwego/hertz/pkg/protocol/sse"
56+
57+
sse.AddAcceptMIME(req) // 部分SSE Server可能会要求显式增加 Accept: text/event-stream
58+
sse.SetLastEventID(req, "id-123") // 对于有状态服务,需要通过 SetLastEventID 告诉 Server
59+
```
60+
61+
### 处理返回
62+
```go
63+
import "github.com/cloudwego/hertz/pkg/protocol/sse"
64+
65+
func HandleSSE(ctx context.Context, resp *protocol.Response) error {
66+
r, err := sse.NewReader(resp)
67+
if err != nil {
68+
return err
69+
}
70+
71+
// 也可以手动调用 r.Read 方法
72+
err = r.ForEach(ctx, func(e *Event) error {
73+
println("Event:", e.String())
74+
return nil
75+
})
76+
if err != nil { // 如果 Server 正常断开,这里 err == nil,不会报错
77+
// 其他io错误 或 ctx cancelled
78+
return err
79+
}
80+
println("Client LastEventID", r.LastEventID()) // 可用于保存最后接收的 Event ID
81+
return nil
82+
}
83+
```
84+
85+
### 常见问题
86+
87+
#### 如何实现多级的 SSE / SSE Proxy?
88+
- 可以同时参考 Client 端和 Server端的实现
89+
- Server 启用 `WithSenseClientDisconnection` 并且把 context 传入 下一跳的 Reader ForEach
90+
- 这样当Client断开时,会自动识别,并且中断整个流
91+
92+
## Event 结构体
93+
```go
94+
// Event represents a Server-Sent Event (SSE).
95+
type Event struct {
96+
ID string // 即 Event ID,sse.Reader 会自动记录最后的 Event ID,可使用 LastEventID() 获取
97+
Type string // 即 Event Type,常见的如 "message"
98+
Data []byte // 为了方便使用 Unmarshal/Marshal,这里使用 []byte,但是按spec这个字段必须要 utf8 string
99+
100+
// 不建议使用,主要是针对浏览器的 SourceEvent 返回该字段控制其重试策略。
101+
// 如果使用Hertz作为Client可以参考:https://www.cloudwego.io/docs/hertz/tutorials/basic-feature/retry/
102+
Retry time.Duration
103+
}
104+
```

0 commit comments

Comments
 (0)