httpsse

package module
v0.0.0-...-8845bbf Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2024 License: MIT Imports: 17 Imported by: 2

README

go-httpsse

Package httpsse implements HTTP server-sent events, for the Go programming language.

As defined by: https://html.spec.whatwg.org/multipage/server-sent-events.html

Documention

Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-httpsse

GoDoc

Examples

Here is an example HTTP SSE server:

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/reiver/go-httpsse"
)

func main() {
	var handler http.Handler = http.HandlerFunc(ServeHTTP)

	err := http.ListenAndServe(":8080", handler)
	if nil != err {
		panic(err)
	}
}

func ServeHTTP(responsewriter http.ResponseWriter, request *http.Request) {

	var route httpsse.Route = httpsse.NewRoute()

	// Send a heartbeat comment every 4.567 seconds.
	httpsse.HeartBeat(4567 * time.Millisecond, route)

	// Spawn this into its own go-routine.
	//
	// Having the things writing to the route run in a different go-routine is important
	// so that the call doesn't block before route.ServeHTTP() is called.
	go loop(route)

	route.ServeHTTP(responsewriter, request)
}

// This function isn't important for this example.
//
// Your own functions would do something useful.
func loop(route httpsse.Route) {
	for {
		err := route.PublishEvent(func(eventwriter httpsse.EventWriter)error{

			if nil == eventwriter {
				panic("nil event-writer")
			}

			var eventName string = "status"
			var eventID string = fmt.Sprintf("status-%d", time.Now().Unix())
			var eventData string = "Hello world!"

			eventwriter.WriteEvent(eventName)
			eventwriter.WriteID(eventID)
			eventwriter.WriteData(eventData)

			return nil
		})
		if nil != err {
			fmt.Printf("PUBLISH-EVENT-ERROR: %s \n", err)
		}

		time.Sleep(2351 * time.Millisecond)
	}
}

Here is an example HTTP SSE client:

package main

import (
	"fmt"

	"github.com/reiver/go-httpsse"
)

func main() {
	const url string = "http://example.com/api/streaming" // REPLACE THIS WITH THE ACTUAL URL.

	client, err := httpsse.DialURL(url)
	if nil != err {
		fmt.Printf("ERROR: had problem dialing %q: %s \n", url, err)
		return
	}
	if nil == client {
		fmt.Println("ERROR: nil client")
		return
	}

	for client.Next() {
		var event httpsse.Event
		err := client.Decode(&event)
		if nil != err {
			fmt.Printf("ERROR: had problem trying to decode the event: %s", err)
			continue
		}

		// You would probably do something useful once you had the event.
		fmt.Println("EVENT:\n", event)
	}
	if err := client.Err(); nil != err {
		fmt.Printf("CLIENT-ERROR: %s", err)
		return
	}
}

Import

To import package httpsse use import code like the follownig:

import "github.com/reiver/go-httpsse"

Installation

To install package httpsse do the following:

GOPROXY=direct go get https://github.com/reiver/go-httpsse

Author

Package httpsse was written by Charles Iliya Krempeaux

Documentation

Index

Constants

View Source
const ContentType string = "text/event-stream"

Variables

This section is empty.

Functions

func HeartBeat

func HeartBeat(wait time.Duration, route Route) io.Closer

HeatBeat sends a heartbeat comment to the 'route' evey 'wait' duration of time.

You want to use this to make sure the HTTP connection does NOT get closed due to inactivity.

You should almost always use this.

Example usage:

func ServeHTTP(resp http.ResponseWriter, req *http.Request) {

	// ...

	var route httpsse.Route = httpsse.NewRoute()

	httpsse.HeatBeat(4 * time.Second, route)

	// ...

	route.ServeHTTP(resp, req)
}

Types

type Client

type Client interface {
	Close() error
	Decode(interface{}) error
	Err() error
	Next() bool
}

Client represents the client side of an HTTP SSE connection.

func Dial

func Dial(httprequest *http.Request) (Client, error)

func DialURL

func DialURL(url string) (Client, error)

type Event

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

An event represents an HTTP server-sent event.

func (Event) Equal

func (receiver Event) Equal(that EventReader) bool

Equal returns whether two events are equal.

Two events arer equal if their event-data, event-id, and event-name are all equal.

func (Event) EventData

func (receiver Event) EventData() string

EventID returns the event-ID

For example, if this is the event:

event: banana
id: yellow-123
data: once
data: twice
data: thirce
data: fource

Then EventID would return:

"once\ntwice\nthrice\nfource"

func (Event) EventID

func (receiver Event) EventID() string

EventID returns the event-ID.

For example, if this is the event:

event: banana
id: yellow-123
data: once
data: twice
data: thirce
data: fource

Then EventID would return:

"yellow-123"

func (Event) EventName

func (receiver Event) EventName() string

EventName returns the event-name.

For example, if this is the event:

event: banana
id: yellow-123
data: once
data: twice
data: thirce
data: fource

Then EventName would return:

"banana"

func (*Event) Reset

func (receiver *Event) Reset()

Reset resets the event to be empty again.

func (*Event) SetEventID

func (receiver *Event) SetEventID(value string)

SetEventID sets the event-ID.

func (*Event) SetEventName

func (receiver *Event) SetEventName(value string)

SetEventName sets the event-name.

func (Event) String

func (receiver Event) String() string

String returns the serialize form of the event, as defined by the HTTP-SSE specification: https://html.spec.whatwg.org/multipage/server-sent-events.html

So, for example, if event-ID is:

"yellow-123"

And, for example. event-name is"

"banana"

And the event-data is:

"once\ntwice\nthrice\nfource"

Then this would return:

": {\n"+
"event: banana\n" +
"id: yello123\n"  +
"data: once\n"    +
"data: twice\n"   +
"data: thice\n"   +
"data: fource\n"  +
": }\n"+
"\n"

func (*Event) Write

func (receiver *Event) Write(p []byte) (int, error)

Write appends event-data.

func (Event) WriteTo

func (receiver Event) WriteTo(writer io.Writer) (n int64, err error)

WriteTo writers the serialized form of the event, as defined by the HTTP-SSE specification: https://html.spec.whatwg.org/multipage/server-sent-events.html

So, for example, if event-ID is:

"yellow-123"

And, for example. event-name is"

"banana"

And the event-data is:

"once\ntwice\nthrice\nfource"

Then this would write:

": {\n"+
"event: banana\n" +
"id: yello123\n"  +
"data: once\n"    +
"data: twice\n"   +
"data: thice\n"   +
"data: fource\n"  +
": }\n"+
"\n"

type EventReader

type EventReader interface {
	EventData() string
	EventID() string
	EventName() string
}

type EventSetter

type EventSetter interface {
	io.Writer
	SetEventName(string)
	SetEventID(string)
}

EventSetter represents an event that can be written to.

Use Write to write the event-data.

Use SetEventName to set the event-name.

Use SetEventID to set the event-ID.

You can give anything that is an EventSetter to Client.Decode

Event is an EventSetter, and can be passed to Client.Decode

But you can also use other types, including creating your own, that are EventSetter, and pass it to Client.Decode

type EventWriter

type EventWriter interface {
	WriteComment(string) error
	WriteData(string) error
	WriteEvent(string) error
	WriteID(string) error
}

type Route

type Route interface {
	io.Closer
	http.Handler
	PublishEvent(func(EventWriter) error) error
}

Route represents a route to send HTTP server-send events (SSEs).

func NewRoute

func NewRoute() Route

NewRoute creates and returns a new Route.

Example usage:

var route httpsse.Route = httpsse.NewRoute()

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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