Skip to content


The response Body can be a callback function taking a huma.Context to facilitate streaming. The huma.StreamResponse utility makes this easy to return:

func handler(ctx context.Context, input *MyInput) (*huma.StreamResponse, error) {
	return &huma.StreamResponse{
		Body: func(ctx huma.Context) {
			// Write header info before streaming the body.
			ctx.SetHeader("Content-Type", "text/my-stream")
			writer := ctx.BodyWriter()

			// Update the write deadline to give us extra time.
			if d, ok := writer.(interface{ SetWriteDeadline(time.Time) error }); ok {
				d.SetWriteDeadline(time.Now().Add(5 * time.Second))
			} else {
				fmt.Println("warning: unable to set write deadline")

			// Write the first message, then flush and wait.
			writer.Write([]byte("Hello, I'm streaming!"))
			if f, ok := writer.(http.Flusher); ok {
			} else {
				fmt.Println("error: unable to flush")

			time.Sleep(3 * time.Second)

			// Write the second message.
			writer.Write([]byte("Hello, I'm still streaming!"))
	}, nil

Also take a look at http.ResponseController which can be used to set timeouts, flush, etc in one simple interface.

Server Sent Events

The sse package provides a helper for streaming Server-Sent Events (SSE) responses that is easier to use than the above example!

Dive Deeper#