wspulse

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2026 License: MIT Imports: 2 Imported by: 0

README

wspulse/core

Shared types for the wspulse WebSocket ecosystem.

This module provides Frame, Codec, JSONCodec, and sentinel errors used by both wspulse/server and wspulse/client-go. It has zero external dependencies (Go stdlib only).

Status: v0 — API is being stabilized. Module path: github.com/wspulse/core.


Install

go get github.com/wspulse/core

Quick Start

import wspulse "github.com/wspulse/core"

// Create a frame
frame := wspulse.Frame{
    ID:      "msg-001",
    Event:    "msg",
    Payload: []byte(`{"text":"hello"}`),
}

// Encode with the default JSON codec
data, err := wspulse.JSONCodec.Encode(frame)
if err != nil {
    log.Fatal(err)
}

// Decode
decoded, err := wspulse.JSONCodec.Decode(data)
if err != nil {
    log.Fatal(err)
}

fmt.Println(decoded.Event) // "msg"

// Check the codec's WebSocket frame type
wspulse.JSONCodec.FrameType() // wspulse.TextMessage (1)
Sentinel errors
if errors.Is(err, wspulse.ErrConnectionClosed) {
    // connection was already closed
}
if errors.Is(err, wspulse.ErrSendBufferFull) {
    // outbound buffer full, frame was dropped
}

Public API

Symbol Description
Frame Transport unit: ID, Event, Payload []byte
Codec Interface: Encode(Frame), Decode([]byte), FrameType() int
JSONCodec Default codec — JSON text frames
TextMessage WebSocket text frame type constant (1)
BinaryMessage WebSocket binary frame type constant (2)
ErrConnectionClosed Sentinel: connection is closed
ErrSendBufferFull Sentinel: send buffer full, frame dropped

Packages

github.com/wspulse/core (root)

Core shared types used across the wspulse ecosystem.

github.com/wspulse/core/router

Gin-style event router for dispatching incoming wspulse.Frame values to registered handlers. Features global middleware, per-event handler chains, a configurable fallback for unmatched frames, and a built-in Recovery() middleware.

Routing key — the "event" JSON field

Every frame is encoded on the wire as a JSON object. The "event" field is what the router uses to select the handler:

{
  "id": "msg-001",
  "event": "chat.message",
  "payload": { "text": "hello" }
}

frame.Event on the Go side maps directly to "event" in JSON. Register handlers with r.On("chat.message", ...) to match that value. The first parameter to On is named event to make this correspondence explicit.

Usage
import (
    "encoding/json"

    wspulse "github.com/wspulse/core"
    "github.com/wspulse/core/router"
)

r := router.New()

// Global middleware — runs before every handler
r.Use(router.Recovery())
r.Use(func(c *router.Context) {
    // authenticate, rate-limit, set metadata …
    c.Set("userID", authenticate(c.Connection))
    c.Next()
})

// Per-event handlers — matched against frame.Event ("event" in JSON)
r.On("chat.message", func(c *router.Context) {
    userID := c.GetString("userID")
    payload, _ := json.Marshal(map[string]any{"ok": true, "from": userID})
    _ = c.Connection.Send(wspulse.Frame{
        Event:   "chat.ack",
        Payload: payload,
    })
})
r.On("ping", func(c *router.Context) {
    _ = c.Connection.Send(wspulse.Frame{Event: "pong"})
})

// Dispatch — call this from WithOnMessage in wspulse/server
r.Dispatch(connection, frame)

Key properties:

  • Routing key is frame.Event, which maps to the "event" field in the JSON wire format
  • Context.Next() / Abort() / IsAborted() flow control (same as Gin)
  • Context.Set / Get / MustGet / GetString typed key-value metadata
  • sync.Pool-backed Context recycling — 0 steady-state allocations per dispatch (metadata map allocated once per pooled Context on first Set; preserved across pool reuses)
  • Lazy chain building: Use or On can be called in any order before the first Dispatch
  • Panics at startup on empty event name or duplicate registration
  • Max chain length: 62 handlers (middleware + route handlers combined)


License

MIT

Documentation

Index

Constants

View Source
const (
	// TextMessage denotes a UTF-8 encoded text WebSocket frame (opcode 1).
	TextMessage = 1

	// BinaryMessage denotes a binary WebSocket frame (opcode 2).
	BinaryMessage = 2
)

WebSocket message type constants. These mirror the standard WebSocket frame types without importing gorilla/websocket, keeping this module free of external dependencies.

Variables

View Source
var (
	// ErrConnectionClosed is returned when sending to a connection that has already been closed.
	ErrConnectionClosed = errors.New("wspulse: connection is closed")

	// ErrSendBufferFull is returned when the outbound buffer is full.
	// The frame is dropped; handle backpressure at the application layer.
	ErrSendBufferFull = errors.New("wspulse: send buffer full, frame dropped")
)

Sentinel errors shared across the wspulse ecosystem.

Functions

This section is empty.

Types

type Codec

type Codec interface {
	// Encode serializes f into bytes ready to be sent as a WebSocket frame.
	Encode(f Frame) ([]byte, error)

	// Decode deserializes received WebSocket bytes into a Frame.
	Decode(data []byte) (Frame, error)

	// FrameType returns the WebSocket message type to use when sending:
	// TextMessage (1) or BinaryMessage (2).
	FrameType() int
}

Codec encodes and decodes Frames for transmission over a WebSocket connection.

var JSONCodec Codec = jsonCodec{}

JSONCodec is the default Codec. Frames are encoded as JSON text frames. Frame.Payload must be valid JSON bytes (e.g. the output of json.Marshal).

type Frame

type Frame struct {
	// ID uniquely identifies this frame. Used for ACK correlation.
	// If empty on Send, no ID is set on the wire.
	ID string

	// Event identifies the frame purpose. wspulse does not interpret this value.
	// Conventional values: "msg" (user data), "sys" (system event), "ack" (acknowledgement).
	Event string

	// Payload is the encoded message body. Its format is determined by the Codec.
	Payload []byte
}

Frame is the minimal transport unit for all WebSocket communication. Payload bytes are opaque to the wspulse layer; their format depends on the Codec in use. When using JSONCodec (the default), Payload must be valid JSON bytes (e.g. output of json.Marshal). When using a binary codec, Payload is the codec-encoded bytes.

Directories

Path Synopsis
Package router provides Gin-style event routing for wspulse frames.
Package router provides Gin-style event routing for wspulse frames.

Jump to

Keyboard shortcuts

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