Documentation
¶
Overview ¶
Package router provides Gin-style event routing for wspulse frames. Inbound frames are dispatched by wspulse.Frame.Event through a middleware chain with flow control (Context.Next/Context.Abort) and metadata passing (Context.Set/Context.Get).
Typical usage:
rtr := router.New()
rtr.Use(router.Recovery())
rtr.On("chat.message", handleChat)
rtr.On("chat.join", handleJoin)
// Integrate with wspulse/server:
srv := server.NewServer(connectFunc,
server.WithOnMessage(func(connection server.Connection, frame wspulse.Frame) {
rtr.Dispatch(connection, frame)
}),
)
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Connection ¶
type Connection interface {
// ID returns the unique connection identifier.
ID() string
// RoomID returns the room this connection belongs to.
RoomID() string
// Send enqueues frame for delivery to the remote peer.
Send(frame wspulse.Frame) error
// Close initiates a graceful shutdown of the session.
Close() error
// Done returns a channel that is closed when the session terminates.
Done() <-chan struct{}
}
Connection represents the logical WebSocket session from the router's perspective. It is a consumer-defined interface: any type that provides these five methods satisfies it.
wspulse/server's server.Connection satisfies this interface via Go structural subtyping — no adapter is required.
type Context ¶
type Context struct {
// Connection is the logical WebSocket session that sent the frame.
Connection Connection
// Frame is the decoded inbound frame being dispatched.
Frame wspulse.Frame
// contains filtered or unexported fields
}
Context carries the state for a single frame dispatch. It is obtained from a sync.Pool and reset between dispatches; callers must not hold a reference to a Context after the handler returns.
Context and its handlers are not concurrency-safe. All methods must be called from the goroutine that performs dispatch, and callers are expected to enforce serial handler execution per logical connection.
func (*Context) Abort ¶
func (c *Context) Abort()
Abort prevents any remaining handlers in the chain from being called. The current handler continues executing normally after Abort; only subsequent handlers are skipped.
func (*Context) GetString ¶
GetString returns the string value stored under key, or "" if the key does not exist or its value is not a string.
func (*Context) MustGet ¶
MustGet returns the value stored under key. It panics if the key does not exist.
type HandlerFunc ¶
type HandlerFunc func(*Context)
HandlerFunc is the function signature for all router handlers and middleware. The *Context argument carries the inbound connection, frame, flow control methods, and a per-dispatch key/value store.
func Recovery ¶
func Recovery() HandlerFunc
Recovery returns a HandlerFunc that catches any panic raised by downstream handlers in the chain. On recovery, it logs the panic value and the full stack trace at ERROR level via log/slog and then returns normally, keeping the connection alive.
Place Recovery as the first middleware so it wraps the entire chain:
r := router.New()
r.Use(router.Recovery())
r.On("chat.message", handleChat)
type HandlersChain ¶
type HandlersChain []HandlerFunc
HandlersChain is an ordered slice of HandlerFunc values representing a middleware + handler pipeline.
type Option ¶
type Option func(*Router)
Option is a functional option for configuring a Router.
func WithFallback ¶
func WithFallback(fn HandlerFunc) Option
WithFallback sets a custom handler invoked when no route matches the incoming frame's Event. The fallback participates in the normal handler chain, so global middleware registered via Use runs before it.
The default fallback logs the unmatched frame event at WARN level using the standard library's log/slog package.
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router dispatches inbound wspulse frames to registered handlers based on Frame.Event. It supports global middleware (Use), per-event handlers (On), and a configurable fallback for unmatched frames.
Router is safe for concurrent reads after all routes have been registered. Do not call On or Use concurrently with Dispatch.
func New ¶
New returns a new Router with the provided options applied. The default fallback logs unmatched frame events at WARN level.
func (*Router) Dispatch ¶
func (r *Router) Dispatch(conn Connection, frame wspulse.Frame)
Dispatch looks up the handler chain for frame.Event and executes it. If no handler is registered for frame.Event, the fallback is called instead. Global middleware runs before the matched handler or fallback in all cases.
Dispatch is safe to call concurrently from multiple goroutines after all routes have been registered. However, calling Use or On while Dispatch is running is not safe.
func (*Router) On ¶
func (r *Router) On(event string, handlers ...HandlerFunc)
On registers one or more handlers for the given Frame.Event value ("event" in JSON). Panics if event is empty, if no handlers are provided, if any handler is nil, or if event is already registered. On must not be called concurrently with Dispatch.
func (*Router) Use ¶
func (r *Router) Use(handlers ...HandlerFunc)
Use appends one or more middleware handlers to the global middleware chain. Global middleware runs before every handler, including the fallback. Use must not be called concurrently with Dispatch.