@@ -3,27 +3,20 @@ title: "SSE"
33date : 2025-05-21
44weight : 19
55keywords : ["SSE"]
6- description : " SSE in Hertz"
6+ description : " SSE capabilities provided by Hertz"
77---
8- ``` Code:https://github.com/cloudwego/hertz/tree/develop/pkg/protocol/sse ```
9-
10- ** Changelog**
11-
12- - 2025/05/15 Has been released to the open-source version v0.10.0
13- - 2025/05/13 [ d3c68463] Added Get / SetLastEventID.
14- - 2025/05/13 [ 3952e956] The Reader ForEach interface supports passing in ctx.
15- - 2025/04/24 [ cf38573ce] First version completed
8+ ``` code: https://github.com/cloudwego/hertz/tree/develop/pkg/protocol/sse ```
169
1710## What is Server-Sent Events (SSE)
1811
19- - SSE is an HTML standard used to describe the implementation of the EventSource API in browsers . Strictly speaking, it is not an HTTP protocol.
20- - Both the popular Model Context Protocol (MCP) and Agent2Agent (A2A) protocols are based to some extent on SSE
12+ - SSE is an HTML standard used to describe the implementation of browser EventSource API. Strictly speaking, it's not an HTTP protocol.
13+ - Popular protocols like Model Context Protocol (MCP) or Agent2Agent (A2A) are based on SSE to some extent
2114 - https://www.anthropic.com/news/model-context-protocol
2215 - https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
2316
24- ## Server Implementation
17+ ## Server-side Implementation
2518
26- ### Return data
19+ ### Returning Data
2720
2821``` go
2922import " github.com/cloudwego/hertz/pkg/protocol/sse"
@@ -35,78 +28,79 @@ func HandleSSE(ctx context.Context, c *app.RequestContext) {
3528 w.WriteEvent (" id-x" , " message" , []byte (" hello\n\n world" ))
3629 time.Sleep (10 * time.Millisecond )
3730 }
38- w.Close () // Send the last chunk of data to ensure graceful exit. Optional, Hertz will automatically call this after the Handler returns.
31+ w.Close () // Send the last chunk of data to ensure graceful exit. Optional, Hertz will automatically call it after the Handler returns.
3932
40- // Please make sure that the lifecycle of the writer is consistent with that of the handler. Do not use it in asynchronous background.
33+ // Please ensure the writer's lifecycle is consistent with the handler. Don't use it asynchronously in the background.
4134}
4235```
4336
44- ### FAQ
37+ ### Common Issues
4538
4639#### connection has been closed when flush
4740
48- Reason: The client connection has been disconnected, possibly due to a long time without response data. Please check the corresponding configuration.
41+ Reason:
42+ Client connection is disconnected, possibly due to no response data for too long. Please check the relevant configuration.
4943
50- ## Client Implementation
44+ ## Client-side Implementation
5145
52- ### Initiate a request
46+ ### Initiating a Request
5347
54- It's exactly the same as making a normal HTTP request to Hertz.
55- Note: The new Hertz version will automatically recognize SSE streams, so you don't need to explicitly set ` WithResponseBodyStream(true) `
48+ It's exactly the same as initiating a regular HTTP request with Hertz.
49+ Note: New Hertz versions will automatically identify SSE streams, so you don't need to explicitly set WithResponseBodyStream(true)
5650
57- ** Some optional headers **
51+ ** Some Optional Headers **
5852
5953``` go
6054import " github.com/cloudwego/hertz/pkg/protocol/sse"
6155
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
56+ sse.AddAcceptMIME (req) // Some SSE Servers may require explicitly adding Accept: text/event-stream
57+ sse.SetLastEventID (req, " id-123" ) // For stateful services, you need to tell the Server through SetLastEventID
6458```
6559
66- ### Handle response
60+ ### Handling Responses
6761
6862``` go
6963import " github.com/cloudwego/hertz/pkg/protocol/sse"
7064
7165func HandleSSE (ctx context .Context , resp *protocol .Response ) error {
7266 r , err := sse.NewReader (resp)
7367 if err != nil {
74- return err
68+ return err
7569 }
76-
77- // You can also call the r.Read method manually
70+
71+ // You can also manually call the r.Read method
7872 err = r.ForEach (ctx, func (e *Event) error {
7973 println (" Event:" , e.String ())
8074 return nil
8175 })
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
76+ if err != nil { // If the Server disconnects normally, err == nil, no error will be reported
77+ // Other IO errors or ctx cancelled
8478 return err
8579 }
8680 println (" Client LastEventID" , r.LastEventID ()) // Can be used to save the last received Event ID
8781 return nil
8882}
8983```
9084
91- ### FAQ
85+ ### Common Issues
9286
93- #### How to implement multi-level SSE/ SSE Proxy?
87+ #### How to implement multi-level SSE / SSE Proxy?
9488
95- - You can refer to the implementations on both the Client and Server sides simultaneously
96- - Enable ` WithSenseClientDisconnection ` in the server and pass the context to the next hop's Reader ForEach
97- - In this way, when the Client disconnects, it will be automatically recognized, and the entire stream will be interrupted
89+ - You can refer to both Client-side and Server-side implementations
90+ - Enable ` WithSenseClientDisconnection ` on the Server and pass the context to the next hop's Reader ForEach
91+ - This way, when the Client disconnects, it will be automatically detected and the entire stream will be interrupted
9892
99- ## Event Struct
93+ ## Event Structure
10094
10195``` go
10296// Event represents a Server-Sent Event (SSE).
10397type Event struct {
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
98+ ID string // This is the Event ID, sse.Reader will automatically record the last Event ID, which can be obtained using LastEventID()
99+ Type string // This is the Event Type, common ones like "message"
100+ Data []byte // For convenience with Unmarshal/Marshal, []byte is used here, but according to the spec, this field must be a utf8 string
107101
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/
102+ // Not recommended to use , mainly for controlling the retry strategy of the browser's SourceEvent .
103+ // If using Hertz as a Client , you can refer to: https://www.cloudwego.io/docs/hertz/tutorials/basic-feature/retry/
110104 Retry time.Duration
111105}
112106```
0 commit comments