Streaming
Open a Server-Sent Events connection with GetStream or PostStream and decode frames onto a channel you own.
The client streams two ways. A Server-Sent Events endpoint is read with GetStream and PostStream, which decode the wire format into typed frames on a channel. A plain large download is read with the Stream flag on Request, which hands back the live body unread.
Server-Sent Events
GetStream and PostStream open the connection, set the SSE request headers, and start a reader goroutine that decodes each line into a StreamResponse. You pass in the channel and own it. The call returns as soon as the reader is running, and the channel is closed on end of stream.
stream := make(chan http.StreamResponse)
if err := client.GetStream(ctx, stream, http.Request{Path: "/events"}); err != nil {
return err
}
for ev := range stream {
switch ev.Type {
case http.StreamResponseTypeData:
fmt.Println("data:", string(ev.Body))
case http.StreamResponseTypeEvent, http.StreamResponseTypeID, http.StreamResponseTypeRetry:
// an event:, id:, or retry: line, its value in ev.Body
case http.StreamResponseTypeComment:
// a comment line beginning with ":"
case http.StreamResponseTypeEOF:
if ev.Error != nil {
return ev.Error
}
}
}Each frame carries a Type that classifies the SSE line. Body holds the decoded value with the data: or event: prefix already stripped. The stream ends with a StreamResponseTypeEOF frame, whose Error is nil for a clean close and set when the read failed partway.
Note
An error status such as 404 on the initial request is delivered as a single StreamResponseTypeEOF frame carrying the status code, the response body, and a non-nil Error, and GetStream also returns that error. Check both the return value and the final frame.
PostStream is the same, taking a PostRequest so you can open a stream with a request body.
stream := make(chan http.StreamResponse)
err := client.PostStream(ctx, stream, http.PostRequest{
Request: http.Request{Path: "/chat"},
Body: prompt,
})Cancel the context to stop reading early. The reader goroutine exits and closes the channel when the connection ends.
Streaming a large body
For a large non-SSE download, set Stream on the request. The response body is not buffered into resp.Body. Instead the live body is handed back as resp.Reader, and Response is itself an io.ReadCloser over it.
resp, err := client.Get(ctx, http.GetRequest{
Request: http.Request{Path: "/files/big.tar", Stream: true},
})
if err != nil {
return err
}
defer resp.Close()
if _, err := io.Copy(dst, resp); err != nil {
return err
}Warning
You own the streamed body and must close it. Close is a no-op on a buffered response, so you can defer it unconditionally right after the call returns.