api

package
v0.0.0-...-d077802 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AuthMiddleware

func AuthMiddleware(tokenStore *TokenStore) aprot.Middleware

AuthMiddleware checks that the connection is authenticated and sets up the user context. It first checks conn.Get for a cached *AuthUser (set by ConnectHookAuth or Login), falling back to a token store lookup by the connection's user ID. Apply this middleware only to handlers that require authentication.

func ConnectHookAuth

func ConnectHookAuth(tokenStore *TokenStore) aprot.ConnectHook

ConnectHookAuth returns a ConnectHook that validates a session cookie at connection time and caches the authenticated user on the connection via conn.Set. This avoids re-loading the user from a store on every request.

Usage:

server.OnConnect(api.ConnectHookAuth(tokenStore))

func LoggingMiddleware

func LoggingMiddleware(opts ...LoggingOptions) aprot.Middleware

LoggingMiddleware logs all requests with timing information. Pass a LoggingOptions to also log the JSON params (with redaction and truncation). The zero-arg form preserves the original method/duration log line.

Example:

server.Use(api.LoggingMiddleware(api.DefaultLoggingOptions()))

func NewRegistry

func NewRegistry(state *SharedState, authMiddleware aprot.Middleware) *aprot.Registry

NewRegistry creates and configures the API registry with all handlers and push events. Middleware is applied per-handler group for safety - you can't accidentally forget to protect an endpoint.

Types

type AuthUser

type AuthUser struct {
	ID       string
	Username string
}

AuthUser represents an authenticated user in the context.

func AuthUserFromContext

func AuthUserFromContext(ctx context.Context) *AuthUser

AuthUserFromContext returns the authenticated user from the context. Returns nil if no user is authenticated.

type CreateUserResponse

type CreateUserResponse struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

type DirectMessageEvent

type DirectMessageEvent struct {
	FromUserID string `json:"from_user_id"`
	FromUser   string `json:"from_user"`
	Message    string `json:"message"`
}

type GetProfileResponse

type GetProfileResponse struct {
	UserID   string `json:"user_id"`
	Username string `json:"username"`
}

type GetTaskResponse

type GetTaskResponse struct {
	ID     string     `json:"id"`
	Name   string     `json:"name"`
	Status TaskStatus `json:"status"`
}

type GetUserResponse

type GetUserResponse struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

type ListUsersResponse

type ListUsersResponse struct {
	Users []User `json:"users"`
}

type LoggingOptions

type LoggingOptions struct {
	// LogParams enables logging the JSON params alongside method/duration.
	LogParams bool

	// RedactKeys lists JSON object keys whose values are replaced with
	// "[REDACTED]" before logging. Comparison is case-insensitive and the
	// walk recurses into nested objects and arrays. Required reading: aprot
	// params are positional, so for handlers like Login(username, password)
	// the wire payload is a top-level JSON array — the field names that
	// would trigger redaction don't appear. Use SkipMethods for those.
	RedactKeys []string

	// SkipMethods lists fully-qualified method names ("Struct.Method") to
	// omit params for entirely. The log line shows params=[REDACTED] for
	// methods in this list. Use this for handlers whose entire input is
	// sensitive (e.g. "PublicHandlers.Login") or for very chatty methods
	// you don't want polluting logs.
	SkipMethods []string

	// MaxParamLen truncates JSON params longer than this many bytes,
	// appending "...(truncated)". A value <= 0 disables truncation.
	MaxParamLen int
}

LoggingOptions configures LoggingMiddleware.

The zero value disables param logging entirely, matching the original LoggingMiddleware behavior.

func DefaultLoggingOptions

func DefaultLoggingOptions() LoggingOptions

DefaultLoggingOptions returns sensible defaults for production logging: params enabled, common sensitive keys redacted, Login skipped, params truncated at 1 KiB.

type LoginResponse

type LoginResponse struct {
	Token    string `json:"token"`
	UserID   string `json:"user_id"`
	Username string `json:"username"`
}

type ProcessBatchResponse

type ProcessBatchResponse struct {
	Processed int      `json:"processed"`
	Results   []string `json:"results"`
}

type ProcessWithSubTasksResponse

type ProcessWithSubTasksResponse struct {
	Completed int `json:"completed"`
}

type ProtectedHandlers

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

ProtectedHandlers implements API methods that require authentication.

func NewProtectedHandlers

func NewProtectedHandlers(state *SharedState) *ProtectedHandlers

NewProtectedHandlers creates a new ProtectedHandlers instance.

func (*ProtectedHandlers) GetProfile

func (h *ProtectedHandlers) GetProfile(ctx context.Context) (*GetProfileResponse, error)

GetProfile returns the authenticated user's profile. This method requires authentication (middleware applied via registry).

func (*ProtectedHandlers) SendMessage

func (h *ProtectedHandlers) SendMessage(ctx context.Context, toUserID string, message string) (*SendMessageResponse, error)

SendMessage sends a direct message to another user. This method requires authentication (middleware applied via registry).

type PublicHandlers

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

PublicHandlers implements public API methods that don't require authentication.

func NewPublicHandlers

func NewPublicHandlers(state *SharedState) *PublicHandlers

NewPublicHandlers creates a new PublicHandlers instance.

func (*PublicHandlers) CreateUser

func (h *PublicHandlers) CreateUser(ctx context.Context, name string, email string) (*CreateUserResponse, error)

CreateUser creates a new user.

func (*PublicHandlers) GetTask

func (h *PublicHandlers) GetTask(ctx context.Context, id string) (*GetTaskResponse, error)

GetTask retrieves a task by ID (demo: returns hardcoded task).

func (*PublicHandlers) GetUser

func (h *PublicHandlers) GetUser(ctx context.Context, id string) (*GetUserResponse, error)

GetUser retrieves a user by ID.

func (*PublicHandlers) ListUsers

func (h *PublicHandlers) ListUsers(ctx context.Context) (*ListUsersResponse, error)

ListUsers returns all users (no request parameter needed).

func (*PublicHandlers) Login

func (h *PublicHandlers) Login(ctx context.Context, username string, password string) (*LoginResponse, error)

Login authenticates a user and returns a token. This is a public method that doesn't require authentication.

func (*PublicHandlers) ProcessBatch

func (h *PublicHandlers) ProcessBatch(ctx context.Context, items []string, delay int) (*ProcessBatchResponse, error)

ProcessBatch processes items with progress reporting. When the request is canceled, it inspects aprot.CancelCause(ctx) to log whether the client hit cancel, the connection dropped, or the server is shutting down — useful for observability and cleanup decisions.

func (*PublicHandlers) ProcessWithSubTasks

func (h *PublicHandlers) ProcessWithSubTasks(ctx context.Context, steps []string, delay int) (*ProcessWithSubTasksResponse, error)

ProcessWithSubTasks demonstrates hierarchical sub-tasks with progress and output.

func (*PublicHandlers) SendNotification

func (h *PublicHandlers) SendNotification(ctx context.Context, message string, level string) (*SystemNotificationEvent, error)

SendNotification sends a notification to the requesting client.

func (*PublicHandlers) StartSharedWork

func (h *PublicHandlers) StartSharedWork(ctx context.Context, title string, steps []string, delay int) error

StartSharedWork creates a shared task visible to all clients. The handler body is the task body — no goroutine needed. The task auto-completes when the handler returns nil, or auto-fails on error.

type SendMessageResponse

type SendMessageResponse struct {
	Sent bool `json:"sent"`
}

type SharedState

type SharedState struct {
	Broadcaster aprot.Broadcaster
	UserPusher  UserPusher
	TokenStore  *TokenStore
	Users       map[string]*User
	AuthUsers   map[string]*AuthUser // username -> AuthUser
	Mu          sync.RWMutex
	NextID      int
}

SharedState holds state shared between handler groups.

func NewSharedState

func NewSharedState(tokenStore *TokenStore) *SharedState

NewSharedState creates a new shared state instance.

type StreamNumberItem

type StreamNumberItem struct {
	Index   int    `json:"index"`
	Label   string `json:"label"`
	DelayMs int    `json:"delayMs"`
}

StreamNumberItem is a single element of the StreamNumbers sequence.

type StreamingHandlers

type StreamingHandlers struct{}

StreamingHandlers demonstrates server-streaming handlers returning iter.Seq / iter.Seq2. Each yielded value is delivered to the client as a separate websocket message, so UIs can populate lists incrementally instead of waiting for the full response.

func NewStreamingHandlers

func NewStreamingHandlers() *StreamingHandlers

NewStreamingHandlers creates a new StreamingHandlers instance.

func (*StreamingHandlers) Failing

func (h *StreamingHandlers) Failing(_ context.Context) (iter.Seq[int], error)

Failing returns a preflight error. The client should observe a rejection on the initial request, not a stream_end error payload.

func (*StreamingHandlers) Numbers

func (h *StreamingHandlers) Numbers(ctx context.Context, count int, delayMs int) (iter.Seq[*StreamNumberItem], error)

Numbers yields `count` sequential items with a configurable delay between each, simulating a server-side generator that produces results over time (e.g. paging through an upstream API one row at a time). E2E tests pass delayMs=0 for fast runs; UI demos pass a few hundred ms so the table fills row-by-row in a visible way.

func (*StreamingHandlers) Pairs

Pairs demonstrates iter.Seq2[K, V]. Items arrive as [key, value] tuples on the TypeScript side.

func (*StreamingHandlers) Panics

func (h *StreamingHandlers) Panics(_ context.Context) (iter.Seq[int], error)

Panics intentionally panics mid-stream. The server recovers the panic and sends a stream_end with an internal-error code. This lets the test suite verify that a crashing handler does not take down the process.

type SystemNotificationEvent

type SystemNotificationEvent struct {
	Message string `json:"message"`
	Level   string `json:"level"` // info, warning, error
}

type TaskMeta

type TaskMeta struct {
	UserName string `json:"userName,omitempty"`
	Error    string `json:"error,omitempty"`
}

type TaskStatus

type TaskStatus string

TaskStatus represents the status of a task.

const (
	TaskStatusCreated   TaskStatus = "created"
	TaskStatusRunning   TaskStatus = "running"
	TaskStatusCompleted TaskStatus = "completed"
	TaskStatusFailed    TaskStatus = "failed"
)

func TaskStatusValues

func TaskStatusValues() []TaskStatus

TaskStatusValues returns all possible TaskStatus values.

type TokenStore

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

TokenStore manages authentication tokens and user lookup.

func NewTokenStore

func NewTokenStore() *TokenStore

NewTokenStore creates a new token store.

func (*TokenStore) Store

func (ts *TokenStore) Store(token string, user *AuthUser)

Store stores a token for a user.

func (*TokenStore) UserByID

func (ts *TokenStore) UserByID(id string) *AuthUser

UserByID returns the user for a given ID, or nil if not found.

func (*TokenStore) Validate

func (ts *TokenStore) Validate(token string) *AuthUser

Validate returns the user for a token, or nil if invalid.

type User

type User struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

type UserCreatedEvent

type UserCreatedEvent struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

type UserPusher

type UserPusher interface {
	PushToUser(userID string, data any)
}

UserPusher interface for sending push messages to specific users.

type UserUpdatedEvent

type UserUpdatedEvent struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

Jump to

Keyboard shortcuts

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