application

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LoggingMiddleware

func LoggingMiddleware(next http.Handler) http.Handler

LoggingMiddleware returns middleware that logs all requests.

func NonceFromContext

func NonceFromContext(ctx context.Context) string

NonceFromContext returns the per-request nonce, or empty string if none.

func RenderError

func RenderError(w http.ResponseWriter, r *http.Request, err error)

RenderError renders an error message (returns 200 for HTMX compatibility). In production (ENV=production), internal error details are hidden to prevent information leakage. Full errors are logged for debugging.

func Serve

func Serve(views embed.FS, opts ...Option)

Serve starts the HTTP server with the given views and options

Types

type App

type App struct {
	Emailer

	// ScriptFunc generates the frontend <script> tags with a nonce.
	// Set by the frontend controller; called per-request in render().
	ScriptFunc func(nonce string) template.HTML
	// contains filtered or unexported fields
}

App is the main application container

func New

func New(opts ...Option) *App

New creates an App and applies the given options. This triggers controller Setup functions, useful for build-time tasks.

func (*App) Controller

func (app *App) Controller(name string, controller Controller)

Controller registers a controller with the application. If the controller has a Setup method, it will be called.

func (*App) Func

func (app *App) Func(name string, fn any)

Func registers a template function with the application. This must be called before templates are parsed (typically in options).

func (*App) Method

func (app *App) Method(controller any, methodName string, bouncer Bouncer) http.Handler

Method creates a handler that calls a controller method with optional bouncer. Validates the method exists and has the correct signature at registration time.

func (*App) RenderToString

func (app *App) RenderToString(name string, data any) (string, error)

RenderToString renders a template to a string. For partials (already in base templates), use just the filename: "live-time.html" For views, use the path relative to views/: "index.html" or "admin/dashboard.html"

func (*App) Serve

func (app *App) Serve(templateName string, bouncer Bouncer) *View

Serve creates a View handler that renders a template

type BaseController

type BaseController struct {
	*App
	*http.Request
}

BaseController is the base type for all controllers. Embed this in your controller structs.

func (*BaseController) IntParam

func (c *BaseController) IntParam(name string, defaultValue int) int

IntParam returns an integer query parameter with a default value

func (*BaseController) IsHTMX

func (c *BaseController) IsHTMX(r *http.Request) bool

IsHTMX returns true if the request is from HTMX

func (*BaseController) QueryParam

func (c *BaseController) QueryParam(name, defaultValue string) string

QueryParam returns a query parameter with a default value

func (*BaseController) Redirect

func (c *BaseController) Redirect(w http.ResponseWriter, r *http.Request, path string)

Redirect sends a redirect response (HX-Location for HTMX, HTTP redirect otherwise)

func (*BaseController) Refresh

func (c *BaseController) Refresh(w http.ResponseWriter, r *http.Request)

Refresh sends an HX-Refresh header to reload the page

func (*BaseController) Render

func (c *BaseController) Render(w http.ResponseWriter, r *http.Request, templateName string, data any)

Render renders a template with optional data

func (*BaseController) RenderError

func (c *BaseController) RenderError(w http.ResponseWriter, r *http.Request, err error)

RenderError delegates to the standalone RenderError function. Kept for backward compatibility with existing controllers.

func (*BaseController) Setup

func (c *BaseController) Setup(app *App)

Setup initializes the controller with the application. Override this in your controller to register routes.

func (*BaseController) Stream

Stream creates a new SSE streamer for real-time updates. Sets appropriate headers and returns a Streamer for sending events.

Example:

func (c *HomeController) Live(w http.ResponseWriter, r *http.Request) {
    stream := c.Stream(w)
    for {
        select {
        case <-r.Context().Done():
            return
        case msg := <-updates:
            stream.Send("messages", "<div>"+msg+"</div>")
        }
    }
}

Template usage with HTMX SSE extension:

<div hx-ext="sse" sse-connect="/live" sse-swap="messages">
    Loading...
</div>

type BaseEmailer

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

BaseEmailer provides common email template rendering functionality. Embed this in your emailer implementations.

func (*BaseEmailer) Init

func (b *BaseEmailer) Init(emails embed.FS, funcs template.FuncMap)

Init initializes the base emailer with templates. Call this in your emailer's constructor.

func (*BaseEmailer) Render

func (b *BaseEmailer) Render(name string, data map[string]any) (string, error)

Render renders an email template to a string

type Bouncer

type Bouncer func(app *App, w http.ResponseWriter, r *http.Request) bool

Bouncer is a function that gates route access. Returns true to allow the request, false to block it.

type Controller

type Controller interface {
	Handle(r *http.Request) Controller
}

Controller is the interface that controllers implement. The Handle method receives the request and returns a controller instance that can be used by templates to access controller methods.

type Emailer

type Emailer interface {
	Send(to, subject, templateName string, data map[string]any) error
}

Emailer is the interface for sending templated emails

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware wraps an http.Handler (e.g. for request interception).

func NonceMiddleware

func NonceMiddleware() Middleware

NonceMiddleware generates a cryptographic nonce per request and stores it in the request context. Retrieve with NonceFromContext.

func SecurityHeaders

func SecurityHeaders() Middleware

SecurityHeaders returns a middleware that sets security response headers on every response. CSP uses a per-request nonce from NonceMiddleware.

The CSP policy:

  • script-src uses nonce + strict-dynamic (CDN scripts loaded by nonce'd scripts inherit trust)
  • 'unsafe-inline' is a CSP2 fallback, ignored by CSP3 browsers when a nonce is present
  • style-src allows 'unsafe-inline' because Tailwind CSS Browser runtime needs it
  • frame-ancestors 'none' replaces X-Frame-Options in CSP-aware browsers

type Option

type Option func(*App)

Option configures the application

func WithController

func WithController(name string, controller Controller) Option

WithController registers a controller with the application. Takes (name, controller) from factory function like controllers.Home().

func WithEmailer

func WithEmailer(emailer Emailer) Option

WithEmailer sets the emailer implementation

func WithFunc

func WithFunc(name string, fn any) Option

WithFunc registers a template function

func WithHealthPath

func WithHealthPath(path string) Option

WithHealthPath sets the path for the auto-registered health endpoint. Defaults to "/health" if not set.

func WithMiddleware

func WithMiddleware(mw Middleware) Option

WithMiddleware adds a middleware to the handler chain. Middlewares are applied in order, with the last-added wrapping outermost.

func WithValue

func WithValue(name string, value any) Option

WithValue registers a template function that returns the given value

func WithViews

func WithViews(views fs.FS) Option

WithViews sets the views filesystem for the application. This is primarily used for testing; production code should use Serve().

type Streamer

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

Streamer provides Server-Sent Events (SSE) streaming. Use with HTMX's SSE extension for real-time updates.

Create via c.Stream(w), which sets SSE headers and flushes immediately.

Three ways to send events:

  • Send(event, data): Named event — client listens via sse-swap="event". Use for HTMX targets where the event name selects which DOM element to swap.

  • SendData(data): Default (unnamed) "message" event — client receives via onmessage or sse-swap="message". Use for simple data push (e.g., JSON payloads consumed by JavaScript, not HTMX swap targets).

  • Render(event, template, data): Named event with server-rendered HTML. Renders a Go template to string and sends it as an SSE event. Use when the server produces the final HTML (the common HTMX pattern). Newlines in rendered HTML are replaced with spaces (safe for HTML, required by SSE spec).

func (*Streamer) Render

func (s *Streamer) Render(event, templateName string, data any) error

Render renders a template and sends it via SSE. For partials, use just the filename (e.g., "live-time.html"). Newlines are replaced with spaces (safe for HTML).

Example:

stream.Render("time", "live-time.html", time.Now().Format("15:04:05"))

func (*Streamer) Send

func (s *Streamer) Send(event, data string) error

Send sends an SSE event with the given name and data. The event name corresponds to sse-swap in HTMX. Newlines in data are properly handled per SSE spec. Returns an error if the write fails (e.g., client disconnected).

func (*Streamer) SendData

func (s *Streamer) SendData(data string) error

SendData sends an SSE message event (default event type). Newlines in data are properly handled per SSE spec. Returns an error if the write fails (e.g., client disconnected).

type View

type View struct {
	*App
	// contains filtered or unexported fields
}

View is an http.Handler that renders a template

func (*View) ServeHTTP

func (v *View) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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