Skip to content

Streaming

HTTP streaming is exposed through ctx.Response().Stream.

func (p *Projects) Export(ctx sdk.Ctx) (any, error) {
ctx.Response().Header("Content-Type", "application/x-ndjson")
return nil, ctx.Response().Stream(func(stream sdk.HTTPStream) error {
for item := range p.Export.ProjectRows(ctx.Context()) {
if err := stream.Write(item.JSONLine()); err != nil {
return err
}
if err := stream.Flush(); err != nil {
return err
}
}
return nil
})
}

Streaming supports:

  • NDJSON.
  • Server-sent events.
  • Chunked downloads.
  • Long-running exports.

sdk.HTTPStream only exposes Context, Write, and Flush. Set status and headers through ctx.Response() before the stream starts:

ctx.Response().Status(http.StatusOK)
ctx.Response().Header("Content-Type", "text/event-stream")

Each response can have one stream handler. Calling ctx.Response().Stream a second time returns an error immediately and leaves the first stream handler in place.

Use stream.Context() or ctx.Context() to observe cancellation. If the client disconnects, the driver cancels the context.

If a stream setup fails before bytes are written, return an error. If streaming fails after the response has begun, the protocol response can already be committed. Treat late stream errors as operational signals, not as a normal client response path.

The standard-library driver returns stream handler errors to the Anvil error pipeline. The Fiber driver writes through Fiber’s body stream callback; errors returned by that callback cannot be converted into an HTTP error response. Log or publish important late-stream failures from the stream handler itself when using Fiber.

Drivers own the concrete flushing behavior. The SDK only exposes the minimal Write and Flush contract.