livereload package

import "code.pfad.fr/devf/livereload"

package livereload handles Server-sent events and injection of the livereload script into upstream HTML pages.

To get started, create a Handler struct, serve it as you wish and call ForwardMessages to trigger reloads.

Example

package main

import (
	"net/http"
	"time"

	"code.pfad.fr/devf/livereload"
)

func main() {
	// Handler wiring
	livereloadHandler := &livereload.Handler{
		// Wire your own http.Handler here (eg http.FileServer)
		Upstream: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// The Content-Type must contain text/html for the livereload script to be injected
			w.Header().Set("Content-Type", "text/html; charset=utf-8")
			w.WriteHeader(200)
		}),
		LogRequest:      livereload.SingleLineRequestLogger(80, false),
		LogSlowResponse: livereload.SlowResponseLogger(time.Second),
	}
	s := http.Server{
		Handler: livereloadHandler,
		Addr:    ":1234",
	}
	go s.ListenAndServe()
	defer s.Close()

	http.Get("http://localhost:1234/") // a livereload script will be injected in HTML responses

	// Reload wiring (usually connected to os.Signal or os.Stdin)
	messages := make(chan string)
	go func() {
		messages <- "reload" // trigger a reload to all connected browsers
		close(messages)
	}()

	livereloadHandler.ForwardMessages(messages, 5*time.Millisecond, time.Second)

}

Functions

func SingleLineRequestLogger

func SingleLineRequestLogger(lineWidthMax int, withColors bool) func(int, *http.Request, time.Duration)

SingleLineRequestLogger will print a colored line for each request, for instance:

200 GET /style.css                                                         300µs
Code Method RequestURI                                              ResponseTime

func SlowResponseLogger

func SlowResponseLogger(timeout time.Duration) func(r *http.Request) chan<- struct{}

SlowResponseLogger will print a colored line for each request when the headers weren't sent within the timeout, for instance:

slow response (>1s)  GET /devf/style.css
RedMessage           Method RequestURI

Types

type Handler

type Handler struct {
	// Required
	Upstream http.Handler

	// If set, LogRequest will be called after an upstream request has been handled.
	LogRequest func(statusCode int, r *http.Request, duration time.Duration)

	// If set, the channel returned by LogSlowResponse will be closed when the
	// response headers for the corresponding request are sent.
	LogSlowResponse func(r *http.Request) chan<- struct{}
	// contains filtered or unexported fields
}

Handler is a wrapper to manage livereloading. Only the Upstream field is required. See [SingleLineRequestLogger] and [SlowResponseLogger] for the optional LogRequest and LogSlowResponse fields.

func (*Handler) ForwardMessages

func (h *Handler) ForwardMessages(messages <-chan string, initialRefreshDelay, minRefreshInterval time.Duration)

ForwardMessages forwards the non-empty messages to the webpage, to trigger a reload. This method returns when the message channel is closed.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles /.devf/* requests and inject the livereload script to html responses of the Upstream http.Handler.

Files

handler.go

logger.go

sse.go

Forge

https://codeberg.org/pfad.fr/devf

git clone

https://codeberg.org/pfad.fr/devf
git@codeberg.org:pfad.fr/devf