router

package module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Jul 8, 2026 License: MIT Imports: 1 Imported by: 0

README

router

Isomorphic routing contract — Context, Router, HandlerFunc identical on native and edge/wasm targets. Defines request handling, streaming (SSE), WebSocket upgrade, and middleware. Modules mount their API via APIModule. The router defines the shape; concrete servers implement it.

Quick Start

import "github.com/tinywasm/router"

type MyModule struct{ name string }

func (m MyModule) ModelName() string { return m.name }
func (m MyModule) MountAPI(r router.Router) {
    r.Get("/api/data", func(ctx router.Context) {
        ctx.WriteStatus(200)
        ctx.Write([]byte("hello"))
    })
}

Caller — the call-side contract

func (v *MyView) Refresh() {
    v.Caller.Call("list_services", nil, func(res []byte, err error) {
        if err != nil {
            v.HandleError(err)
            return
        }
        v.Update(res)
    })
}

Modules and views depend on Caller to invoke server operations without knowing the wire protocol or transport. Adapters live with each transport (e.g. mcp.NewCaller in tinywasm/mcp adapts a JSON-RPC client), while tests use a mock.Caller.

Contracts

  • Context: minimal I/O (read method/path/body, write headers/status) + cookies (SetCookie/Cookie) + identity (SetUserID/UserID)
  • Cookie: isomorphic HTTP cookie type with SameSite policy (SameSiteDefault/Lax/Strict/None)
  • HandlerFunc: func(Context) — the unit of dispatch
  • Route: registration token; supports Requires(resource, action) for RBAC and Public() for explicit public access
  • RouteInfo: read-only view of a registered route with method, path, resource, action, and public flag
  • Router: register routes (Get/Post/Put/Delete/Handle) returning Route + streaming (Stream/Socket) + middleware (Use) + Routes() for introspection
  • Streamer: Context + Flush() for SSE/streaming responses
  • Socket: bidirectional connection (WebSocket)
  • Middleware: func(HandlerFunc) HandlerFunc — transversal logic (auth, logging)
  • APIModule: module + MountAPI(Router) — how modules publish APIs
  • Caller: call-side contract — how a client-side view invokes a named server operation
  • mock: subpackage with canonical test doubles (Router, Context, Route, Caller) — no net/http, WASM-safe

Design

No net/http in the public API. Handlers never import Go's standard library HTTP types. All routing is self-describing via signatures — no runtime type assertions, no hidden machinery.

See docs/PLAN_EXECUTED.md for implementation details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIModule added in v0.1.0

type APIModule interface {
	model.ModuleNaming // aporta ModelName() — identidad
	MountAPI(r Router)
}

APIModule es un módulo que expone una API de servidor. Lo consume el punto de entrada del servidor (!wasm): le pasa el Router del host y el módulo registra sus propias rutas/handlers. Como Router es isomórfico, el módulo nunca importa net/http para describir su API. El transporte concreto (subida binaria, otro protocolo montado como ruta) es decisión interna del módulo.

type Caller added in v0.1.4

type Caller interface {
	// Call invokes op; result/err arrive asynchronously via callback
	// (works for wasm fetch and for in-process test doubles alike).
	// Implementations MUST propagate every error — never swallow.
	Call(op string, args model.Encodable, callback func(result []byte, err error))

	// Dispatch is fire-and-forget (no response expected).
	Dispatch(op string, args model.Encodable)
}

Caller is how a client-side view invokes a named server operation without knowing the wire protocol or transport. It mirrors APIModule: APIModule is the mount-side contract, Caller is the call-side contract.

op is the logical operation name (e.g. "list_services") — NEVER a wire-level method. Translating op to the concrete envelope is the adapter's job (e.g. mcp.NewCaller adapts *mcp.Client). Test doubles satisfy Caller with canned bytes and no transport.

type Context added in v0.1.0

type Context interface {
	Method() string
	Path() string
	Body() []byte
	GetHeader(key string) string
	SetHeader(key, value string)
	WriteStatus(code int)
	Write(b []byte) (int, error)
	// Valores de ámbito de petición (middleware pasa datos al handler siguiente).
	SetValue(key string, v any)
	Value(key string) any
	// Cookies isomórficas.
	SetCookie(c Cookie)                // escribe una cookie en la respuesta
	Cookie(name string) (Cookie, bool) // lee una cookie de la petición; ok=false si no está
	// Identidad de ámbito de petición. Un middleware de autenticación registra
	// quién es el llamador; los handlers y módulos montados la leen.
	SetUserID(id string) // registra la identidad autenticada (id "" = anónimo)
	UserID() string      // lee la identidad; "" si no hay sesión válida
}

Context es la abstracción mínima que ve un handler: petición → respuesta. Idéntica firma en el objetivo nativo (!wasm) y en el objetivo edge/wasm.

type Cookie struct {
	Name     string
	Value    string
	Path     string
	Domain   string
	MaxAge   int // >0 segundos; 0 = sesión; <0 = borrar ahora
	Secure   bool
	HttpOnly bool
	SameSite SameSite
}

Cookie es la representación isomórfica de una cookie HTTP. No referencia net/http: cada implementador concreto la mapea a su transporte (net/http.Cookie en nativo; cabecera Set-Cookie en edge/wasm).

type HandlerFunc added in v0.1.0

type HandlerFunc func(Context)

HandlerFunc es la unidad de despacho: recibe un Context y responde sobre él.

type Middleware added in v0.1.0

type Middleware func(HandlerFunc) HandlerFunc

Middleware envuelve un handler para añadir lógica transversal (auth, logging). Operar SOLO sobre Context — nunca sobre tipos concretos de transporte.

type Route added in v0.1.1

type Route interface {
	// Requires ata un permiso RBAC a la ruta: el par (resource, action). action es string,
	// coincidiendo con la fuente de verdad user.Permission.Action string. Legible y
	// extensible: "write", "read", "orders:export" — no un byte críptico.
	Requires(resource string, action string) Route
	// Public marca la ruta como accesible sin identidad. La ausencia de este
	// marcador (y de Requires) implica que la ruta es privada por defecto.
	Public() Route
}

Route describe una ruta ya registrada y permite anotarla. Lo devuelve cada método de registro del Router. Las anotaciones son declarativas: el contrato no las aplica — cada implementador concreto (serverd nativo, runtime edge) las hace cumplir.

type RouteInfo added in v0.1.1

type RouteInfo struct {
	Method   string
	Path     string
	Resource string // "" = ruta pública (sin RBAC)
	Action   string
	Public   bool // true = accesible sin identidad
}

RouteInfo es la vista de solo lectura de una ruta registrada — para introspección.

type Router

type Router interface {
	Get(path string, h HandlerFunc) Route
	Post(path string, h HandlerFunc) Route
	Put(path string, h HandlerFunc) Route
	Delete(path string, h HandlerFunc) Route
	Options(path string, h HandlerFunc) Route
	Handle(method, path string, h HandlerFunc) Route
	Stream(path string, h StreamFunc) Route
	Socket(path string, h SocketFunc) Route
	Use(m ...Middleware)
	// Routes enumera las rutas registradas y sus metadatos.
	Routes() []RouteInfo
}

Router es aquello sobre lo que un módulo registra sus rutas. Un implementador concreto (servidor nativo, runtime edge) satisface esta interfaz; los módulos y los hosts solo la consumen.

type SameSite added in v0.1.1

type SameSite int

SameSite tipa la política SameSite — estado ilegal no representable (no un string).

const (
	SameSiteDefault SameSite = iota
	SameSiteLax
	SameSiteStrict
	SameSiteNone
)

type Socket added in v0.1.0

type Socket interface {
	Read() ([]byte, error)
	Write(b []byte) error
	Close() error
}

Socket es la conexión bidireccional ya upgradeada (WebSocket). Abstracción isomórfica: no toca mecanismos de upgrade concretos.

type SocketFunc added in v0.1.0

type SocketFunc func(Socket)

SocketFunc es un handler que recibe un Socket tipado.

type StreamFunc added in v0.1.0

type StreamFunc func(Streamer)

StreamFunc es un handler que recibe un Streamer tipado.

type Streamer added in v0.1.0

type Streamer interface {
	Context
	Flush() // envía al cliente lo escrito hasta ahora, sin cerrar la respuesta
}

Streamer es un Context que además empuja lo escrito de inmediato. Usada para respuestas incrementales (SSE, streaming).

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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