11---
22title : " SSE"
33date : 2025-05-21
4- weight : 12
4+ weight : 19
55keywords : ["SSE"]
6- description : " Hertz Support SSE。 "
6+ description : " SSE in Hertz "
77---
88``` Code:https://github.com/cloudwego/hertz/tree/develop/pkg/protocol/sse ```
99
1010** Changelog**
11+
1112- 2025/05/15 Has been released to the open-source version v0.10.0
1213- 2025/05/13 [ d3c68463] Added Get / SetLastEventID.
1314- 2025/05/13 [ 3952e956] The Reader ForEach interface supports passing in ctx.
1415- 2025/04/24 [ cf38573ce] First version completed
1516
16- ## 什么是Server-Sent Events (SSE)
17+ ## What is Server-Sent Events (SSE)
18+
1719- SSE is an HTML standard used to describe the implementation of the EventSource API in browsers. Strictly speaking, it is not an HTTP protocol.
1820- 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+ - https://www.anthropic.com/news/model-context-protocol
22+ - https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
2123
2224## Server Implementation
25+
2326### Return data
27+
2428``` go
2529import " github.com/cloudwego/hertz/pkg/protocol/sse"
2630
@@ -31,73 +35,78 @@ func HandleSSE(ctx context.Context, c *app.RequestContext) {
3135 w.WriteEvent (" id-x" , " message" , []byte (" hello\n\n world" ))
3236 time.Sleep (10 * time.Millisecond )
3337 }
34- w.Close () // 发送最后的chunk数据,确保优雅退出。可选, Hertz 在 Handler 返回后会自动调用。
38+ w.Close () // Send the last chunk of data to ensure graceful exit. Optional, Hertz will automatically call this after the Handler returns.
3539
36- // 请确保 writer 的生命周期和handler一致。不要go异步后台使用。
40+ // Please make sure that the lifecycle of the writer is consistent with that of the handler. Do not use it in asynchronous background.
3741}
3842```
3943
40-
4144### FAQ
45+
4246#### 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.
4447
48+ Reason: The client connection has been disconnected, possibly due to a long time without response data. Please check the corresponding configuration.
4549
4650## Client Implementation
4751
4852### Initiate a request
53+
4954It's exactly the same as making a normal HTTP request to Hertz.
5055Note: The new Hertz version will automatically recognize SSE streams, so you don't need to explicitly set ` WithResponseBodyStream(true) `
5156
5257** Some optional headers**
58+
5359``` go
5460import " github.com/cloudwego/hertz/pkg/protocol/sse"
5561
56- sse.AddAcceptMIME (req) // 部分SSE Server可能会要求显式增加 Accept: text/event-stream
57- sse.SetLastEventID (req, " id-123" ) // 对于有状态服务,需要通过 SetLastEventID 告诉 Server
62+ sse.AddAcceptMIME (req) // Some SSE Servers may require explicit addition of Accept: text/event-stream
63+ sse.SetLastEventID (req, " id-123" ) // For stateful services, you need to tell the Server via SetLastEventID
5864```
5965
6066### Handle response
67+
6168``` go
6269import " github.com/cloudwego/hertz/pkg/protocol/sse"
6370
6471func HandleSSE (ctx context .Context , resp *protocol .Response ) error {
6572 r , err := sse.NewReader (resp)
6673 if err != nil {
67- return err
74+ return err
6875 }
69-
70- // 也可以手动调用 r.Read 方法
76+
77+ // You can also call the r.Read method manually
7178 err = r.ForEach (ctx, func (e *Event) error {
7279 println (" Event:" , e.String ())
7380 return nil
7481 })
75- if err != nil { // 如果 Server 正常断开,这里 err == nil,不会报错
76- // 其他io错误 或 ctx cancelled
82+ if err != nil { // If the Server is disconnected normally, err == nil here, no error will be reported
83+ // Other io errors or ctx cancelled
7784 return err
7885 }
79- println (" Client LastEventID" , r.LastEventID ()) // 可用于保存最后接收的 Event ID
86+ println (" Client LastEventID" , r.LastEventID ()) // Can be used to save the last received Event ID
8087 return nil
8188}
8289```
8390
8491### FAQ
8592
8693#### How to implement multi-level SSE/SSE Proxy?
94+
8795- You can refer to the implementations on both the Client and Server sides simultaneously
8896- 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
97+ - In this way, when the Client disconnects, it will be automatically recognized, and the entire stream will be interrupted
9098
9199## Event Struct
100+
92101``` go
93102// Event represents a Server-Sent Event (SSE).
94103type 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
104+ ID string // Event ID, sse.Reader will automatically record the last Event ID, which can be obtained using LastEventID()
105+ Type string // Event Type, such as "message"
106+ Data []byte // []byte is used here for the convenience of Unmarshal/Marshal, but according to spec, this field must be utf8 string
98107
99- // 不建议使用,主要是针对浏览器的 SourceEvent 返回该字段控制其重试策略。
100- // 如果使用Hertz作为Client可以参考: https://www.cloudwego.io/docs/hertz/tutorials/basic-feature/retry/
108+ // Not recommended, mainly for the browser's SourceEvent to return this field to control its retry strategy.
109+ // If you use Hertz as a client, you can refer to: https://www.cloudwego.io/docs/hertz/tutorials/basic-feature/retry/
101110 Retry time.Duration
102111}
103112```
0 commit comments