sse

package
v0.10.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2025 License: Apache-2.0 Imports: 17 Imported by: 12

Documentation

Overview

Example

Example demonstrates a simple SSE server and client interaction.

// --- SSE Server ---
opt := config.NewOptions([]config.Option{})
opt.Addr = "127.0.0.1:0"
engine := route.NewEngine(opt)
engine.GET("/", func(ctx context.Context, c *app.RequestContext) {
	println("Server Got LastEventID", GetLastEventID(&c.Request))
	w := NewWriter(c)
	for i := 0; i < 5; i++ {
		w.WriteEvent(fmt.Sprintf("id-%d", i), "message", []byte("hello\n\nworld"))
		time.Sleep(10 * time.Millisecond)
	}
	// [optional] it writes 0\r\n\r\n to indicate the end of chunked response
	// hertz will do it after handler returns
	w.Close()
})
go engine.Run()
defer engine.Close()
time.Sleep(20 * time.Millisecond) // wait for server to start
opt.Addr = testutils.GetListenerAddr(engine)

// --- SSE Client ---
c, _ := client.NewClient()
req, resp := protocol.AcquireRequest(), protocol.AcquireResponse()
req.SetRequestURI("http://" + opt.Addr + "/")
req.SetMethod("GET")
req.SetHeader(LastEventIDHeader, "id-0")

// adds `text/event-stream` to http `Accept` header
// may required for some Model Context Protocol(MCP) servers
AddAcceptMIME(req)

if err := c.Do(context.Background(), req, resp); err != nil {
	panic(err)
}
r, err := NewReader(resp)
if err != nil {
	panic(err)
}
defer r.Close()

ctx, cancel := context.WithCancel(context.Background())
go func() {
	time.Sleep(200 * time.Millisecond)
	// cancel can be used to force ForEach returns by closing the remote connection
	_ = cancel
}()
err = r.ForEach(ctx, func(e *Event) error {
	println("Event:", e.String())
	return nil
})
if err != nil {
	panic(err)
}
println("Client LastEventID", r.LastEventID())

Index

Examples

Constants

View Source
const LastEventIDHeader = "Last-Event-ID"

Variables

This section is empty.

Functions

func AddAcceptMIME

func AddAcceptMIME(req *protocol.Request)

AddAcceptMIME adds `text/event-stream` to http `Accept` header.

This is NOT required as per spec: * User agents MAY set (`Accept`, `text/event-stream`) in request's header list.

func GetLastEventID

func GetLastEventID(req *protocol.Request) string

GetLastEventID returns the value of the Last-Event-ID header.

func SetLastEventID

func SetLastEventID(req *protocol.Request, id string)

SetLastEventID sets the Last-Event-ID header.

Types

type Event

type Event struct {
	ID   string
	Type string // aka `event` field, which means event type
	Data []byte

	// hertz only supports reading and writing the field,
	// and will not take care of retry policy, please implement on your own.
	Retry time.Duration
	// contains filtered or unexported fields
}

Event represents a Server-Sent Event (SSE).

func NewEvent

func NewEvent() *Event

NewEvent creates a new event.

Call `Release` when you're done with the event.

func (*Event) AppendData

func (e *Event) AppendData(data []byte)

AppendData appends data to the event data.

func (*Event) AppendDataString

func (e *Event) AppendDataString(data string)

AppendDataString appends string data to the event data.

func (*Event) Clone

func (e *Event) Clone() *Event

Clone creates a copy of the event.

When it's no longer needed, call `Release` to return it to the pool.

func (*Event) IsSetData

func (e *Event) IsSetData() bool

IsSetData returns true if the event data is set.

Please use SetData to set or AppendData to append the event data for differentiating notset or empty

func (*Event) IsSetID

func (e *Event) IsSetID() bool

IsSetID returns true if the event ID is set.

Please use SetID to set the event ID for differentiating notset or empty

func (*Event) IsSetRetry

func (e *Event) IsSetRetry() bool

IsSetRetry returns true if the retry duration is set.

Please use SetRetry to set the event retry duration for differentiating notset or empty

func (*Event) IsSetType

func (e *Event) IsSetType() bool

IsSetType returns true if the event type is set.

Please use SetEvent to set the event type for differentiating notset or empty

func (*Event) Release

func (e *Event) Release()

Release releases the event back to the pool.

func (*Event) Reset

func (e *Event) Reset()

Reset resets the event fields.

func (*Event) SetData

func (e *Event) SetData(data []byte)

SetData sets the event data.

func (*Event) SetDataString

func (e *Event) SetDataString(data string)

SetDataString sets the event data from a string.

func (*Event) SetEvent

func (e *Event) SetEvent(eventType string)

SetEvent sets the event type.

func (*Event) SetID

func (e *Event) SetID(id string)

SetID sets the event ID.

func (*Event) SetRetry

func (e *Event) SetRetry(retry time.Duration)

SetRetry sets the retry duration.

func (*Event) String

func (e *Event) String() string

String returns a string representation of the event.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader represents a reader for Server-Sent Events (SSE).

It is used to parse the response body and extract individual events.

func NewReader

func NewReader(resp *protocol.Response) (*Reader, error)

NewReader creates a new SSE reader from the given response.

It returns an error if the response's content type is not text/event-stream.

func (*Reader) Close

func (r *Reader) Close() error

Close closes the underlying response body.

NOTE: * MUST NOT call Close() and Read() / ForEach() concurrently to avoid race issue.

func (*Reader) ForEach

func (r *Reader) ForEach(ctx context.Context, f func(e *Event) error) error

ForEach iterates over all SSE events in the response body, invoking the provided handler function for each event.

The handler MUST NOT keep the Event reference after returning. Use (*Event).Clone to create a copy if needed.

Iteration stops when:

  • The handler returns an error
  • Reading fails (e.g., bufio.ErrTooLong for events exceeding buffer size)
  • Context is cancelled (if ctx.Done() != nil)
  • All events are processed (returns nil)

func (*Reader) LastEventID

func (r *Reader) LastEventID() string

LastEventID returns the last event ID read by the reader.

func (*Reader) Read

func (r *Reader) Read(e *Event) error

Read reads a single SSE event from the response body.

It populates the provided Event struct with the parsed data. Returns nil on success, io.EOF when no more events, or an error (e.g., bufio.ErrTooLong if an event line exceeds the buffer size). Use SetMaxBufferSize to handle larger events.

func (*Reader) SetMaxBufferSize added in v0.10.2

func (r *Reader) SetMaxBufferSize(max int)

SetMaxBufferSize sets the maximum buffer size for the scanner.

The scanner will allocate its own buffer as needed, up to max bytes. The default max size without calling this method is bufio.MaxScanTokenSize (64KB).

It panics if it is called after reading event has started.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer represents a writer for Server-Sent Events (SSE).

It is used to write individual events to the response body.

func NewWriter

func NewWriter(c *app.RequestContext) *Writer

NewWriter creates a new SSE writer.

func (*Writer) Close

func (w *Writer) Close() error

func (*Writer) Write

func (w *Writer) Write(e *Event) error

Write writes a single SSE event to the response body.

It returns an error if the event contains invalid characters or underlying writer fails.

func (*Writer) WriteComment

func (w *Writer) WriteComment(s string) error

WriteComment writes comment lines to the response body.

Client-side will ignore lines starting with a U+003A COLON character (:) see: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation

func (*Writer) WriteEvent

func (w *Writer) WriteEvent(id, eventType string, data []byte) error

WriteEvent writes a single SSE event to the response body.

If id, eventType, or data are zero-length, they will be ignored. It returns an error if the event contains invalid characters or if the underlying writer fails.

func (*Writer) WriteKeepAlive

func (w *Writer) WriteKeepAlive() error

WriteKeepAlive writes a comment line with "keep-alive" to the response body.

It keeps the underlying connection alive, which is useful when using proxy servers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL