Based on https://github.com/nnevatie/capnwebcpp
Go 49.6%
Svelte 36.1%
JavaScript 12.3%
HTML 1.4%
CSS 0.6%
15 1 0

Clone this repository

https://tangled.org/alex.mcroberts.me/gocapnweb
git@tangled.org:alex.mcroberts.me/gocapnweb

For self-hosted knots, clone URLs may differ based on your setup.

README.md

gocapnweb#

Cap'n Web Go Server Library. This library allows you to create server implementations for the Cap'n Web RPC protocol in Go, providing the minimal plumbing required for getting messages flying between RPC clients and servers.

Features#

  • WebSocket RPC: Real-time bidirectional RPC over WebSockets
  • HTTP Batch RPC: Batched RPC calls over HTTP POST for optimal pipelining performance
  • Pipeline References: Chain RPC calls where one call's result is used as input to another
  • Static File Serving: Serve static files with proper MIME types and security checks
  • Goroutine-Safe: Thread-safe session management with proper synchronization

Dependencies#

Installation#

go get github.com/gocapnweb

Examples#

Running the Examples#

  1. Hello World:

    cd examples/helloworld
    go run main.go
    

    In a second tab:

    cd static
    npm install
    npm run dev
    

    Open: http://localhost:3000

  2. Batch Pipelining:

    cd examples/batch-pipelining  
    go run main.go
    

    In a second tab:

    cd static
    npm install
    npm run dev
    

    Open: http://localhost:3000

  3. Server Push

    cd examples/serverpush
    go run main.go
    

    In a second tab:

    cd static
    npm install
    npm run dev
    

    Open: http://localhost:3000

  4. Bluesky

    cd examples/bluesky
    go run main.go
    

    In a second tab:

    cd static
    npm install
    npm run dev
    

    Open: http://localhost:3000

Getting Started#

Simple Hello World Server#

package main

import (
    "encoding/json"
    "log"
    "net/http"
    
    "github.com/gocapnweb"
    "github.com/gorilla/mux"
)

// Create a simple RPC target
type HelloServer struct {
    *gocapnweb.BaseRpcTarget
}

func NewHelloServer() *HelloServer {
    server := &HelloServer{
        BaseRpcTarget: gocapnweb.NewBaseRpcTarget(),
    }
    
    // Register the hello method
    server.Method("hello", func(args json.RawMessage) (interface{}, error) {
        var argArray []string
        if err := json.Unmarshal(args, &argArray); err != nil {
            return nil, err
        }
        
        if len(argArray) == 0 {
            return "Hello, World!", nil
        }
        
        return "Hello, " + argArray[0] + "!", nil
    })
    
    return server
}

func main() {
    router := mux.NewRouter()
    
    // Setup RPC endpoint
    server := NewHelloServer()
    gocapnweb.SetupRpcEndpoint(router, "/api", server)
    
    // Setup static file serving
    gocapnweb.SetupFileEndpoint(router, "/static", "./static")
    
    log.Println("Server starting on :8000")
    log.Fatal(http.ListenAndServe(":8000", router))
}

Using Custom RPC Target#

You can implement the RpcTarget interface directly for more control:

type CustomServer struct {
    // your fields
}

func (s *CustomServer) Dispatch(method string, args json.RawMessage) (interface{}, error) {
    switch method {
    case "myMethod":
        return s.handleMyMethod(args)
    default:
        return nil, fmt.Errorf("method not found: %s", method)
    }
}

Key Components#

RpcTarget Interface#

The core interface that your server must implement:

type RpcTarget interface {
    Dispatch(method string, args json.RawMessage) (interface{}, error)
}

BaseRpcTarget#

A convenient base implementation with method registration:

server := gocapnweb.NewBaseRpcTarget()
server.Method("methodName", handlerFunc)

Session Management#

Each WebSocket connection or HTTP batch request gets its own session with:

  • Pipeline reference resolution
  • Export ID management
  • Result caching
  • Thread-safe operations

Protocol Support#

WebSocket RPC#

Real-time bidirectional communication:

  • Connect to ws://yourserver/api
  • Send/receive JSON-RPC messages
  • Automatic session management

HTTP Batch RPC#

Optimized for pipelining multiple dependent calls:

  • POST to /api with newline-separated JSON messages
  • Single round trip for multiple dependent operations
  • Automatic pipeline reference resolution

Pipeline References#

Chain operations efficiently:

// Client-side example
const api = newHttpBatchRpcSession('http://localhost:8000/rpc');
const user = api.authenticate('session-token');
const profile = api.getUserProfile(user.id);  // user.id resolved automatically
const notifications = api.getNotifications(user.id);

// All three calls made in a single HTTP request!
const [u, p, n] = await Promise.all([user, profile, notifications]);