testpass: github.com/tmazeika/testpass/sse Index | Examples | Files

package sse

import "github.com/tmazeika/testpass/sse"

Package sse implements functions to send events to a Server-Sent Events (SSE) stream. The format conforms to the ABNF specification here: https://www.w3.org/TR/eventsource/#parsing-an-event-stream.

Index

Examples

Package Files

http.go sse.go

func NewMiddleware Uses

func NewMiddleware(h http.Handler) http.Handler

func Send Uses

func Send(w io.Writer, events ...Event) (n int, err error)

Send sends the given events, in order, to a writer, returning the number of bytes written and any error.

If the writer implements http.Flusher, the Flush function is called before Send returns. An extra newline always follows the last event.

Code:

package main

import (
    "bytes"
    "fmt"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
    "github.com/suiteserve/suiteserve/sse"
    "io/ioutil"
    "strconv"
    "testing"
)

func TestSendWithBom(t *testing.T) {
    var out bytes.Buffer
    n, err := sse.SendWithBom(&out, sse.WithId("123"),
        sse.WithData("hello, world"))
    require.Nil(t, err)
    const want = "\ufeffid:123\ndata:hello, world\n\n"
    assert.Equal(t, len(want), n)
    assert.Equal(t, want, out.String())
}

var sendTests = []struct {
    events []sse.Event
    want   string
}{
    {
        want: "\n",
    },
    {
        events: []sse.Event{sse.WithComment("abc  ")},
        want:   ":abc  \n\n",
    },
    {
        events: []sse.Event{
            sse.WithComment("abc\rcba"),
            sse.WithComment("def\r fed"),
        },
        want: ":abc\n:cba\n:def\n: fed\n\n",
    },
    {
        events: []sse.Event{
            sse.WithId("123"),
            sse.WithEventType("abc\r\n c\n\rba"),
        },
        want: "id:123\nevent:abc\nevent:  c\nevent\nevent:ba\n\n",
    },
    {
        events: []sse.Event{
            sse.WithData(" a,b,c"),
            sse.WithComment(" Hello,  world!"),
        },
        want: "data:  a,b,c\n: Hello,  world!\n\n",
    },
    {
        events: []sse.Event{
            sse.WithRetry(1),
            sse.WithEventType("x\r\n\n\ry"),
            sse.WithId("  ab"),
            sse.WithData("hi"),
        },
        want: "retry:1\nevent:x\nevent\nevent\nevent:y\nid:   ab\ndata:hi\n\n",
    },
    {
        events: []sse.Event{sse.WithRetry(0), sse.WithData("a,b\r\n,c")},
        want:   "retry:0\ndata:a,b\ndata:,c\n\n",
    },
}

func TestSend(t *testing.T) {
    for i, st := range sendTests {
        t.Run(strconv.Itoa(i), func(t *testing.T) {
            var out bytes.Buffer
            n, err := sse.Send(&out, st.events...)
            require.Nil(t, err)
            assert.Equal(t, len(st.want), n)
            assert.Equal(t, st.want, out.String())
        })
    }
}

var sendBenchmark = []sse.Event{
    sse.WithComment("keep-alive"),
    sse.WithId("1badb002"),
    sse.WithEventType("insert"),
    sse.WithData("Lorem\r\nipsum\ndolor\rsit\n\ramet."),
    sse.WithRetry(500),
}

func BenchmarkSend(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _, _ = sse.Send(ioutil.Discard, sendBenchmark...)
    }
}

func main() {
    var w bytes.Buffer
    _, err := sse.Send(&w, sse.WithComment("This is a\n comment."),
        sse.WithData("Hello\nthere,\r\n world\r!"),
        sse.WithId("123"))
    if err != nil {
        panic(err)
    }
    _, err = sse.Send(&w, sse.WithRetry(50), sse.WithRetry(100))
    if err != nil {
        panic(err)
    }
    fmt.Println(w.String())
}

func SendWithBom Uses

func SendWithBom(w io.Writer, events ...Event) (n int, err error)

SendWithBom sends a byte-order mark (BOM) followed by the given events, in order, to a writer, returning the number of bytes written and any error. A BOM must only appear at the start of an SSE stream, therefore this function should not be called after a call to Send on the same writer. It is rare to need to use this function at all.

If the writer implements http.Flusher, the Flush function is called before SendWithBom returns. An extra newline always follows the last event.

type Event Uses

type Event func(w io.Writer) (n int, err error)

func WithComment Uses

func WithComment(s string) Event

WithComment returns an Event that writes comment events to the stream.

func WithData Uses

func WithData(s string) Event

WithData returns an Event that writes data events to the stream.

func WithEventType Uses

func WithEventType(s string) Event

WithEventType returns an Event that writes event type events to the stream.

func WithId Uses

func WithId(s string) Event

WithId returns an Event that writes ID events to the stream.

func WithRetry Uses

func WithRetry(i uint64) Event

WithRetry returns an Event that writes retry events to the stream.

Package sse imports 4 packages (graph). Updated 2020-11-24. Refresh now. Tools for package owners.