oRPC

Features

oRPC extension capabilities

ORPC Interface

The extension exposes a comprehensive ORPC interface:

type ORPC interface {
    RegisterMethod(method *Method) error
    GetMethod(name string) (*Method, error)
    ListMethods() []Method
    GenerateMethodFromRoute(route forge.RouteInfo) (*Method, error)
    HandleRequest(ctx context.Context, req *Request) *Response
    HandleBatch(ctx context.Context, requests []*Request) []*Response
    OpenRPCDocument() *OpenRPCDocument
    Use(interceptor Interceptor)
    GetStats() ServerStats
    SetRouter(router forge.Router)
}

JSON-RPC 2.0 Compliance

Fully compliant JSON-RPC 2.0 server with proper error codes, parameter validation, and result handling:

// Request
{"jsonrpc": "2.0", "method": "users.create", "params": {"name": "Alice"}, "id": 1}

// Success response
{"jsonrpc": "2.0", "result": {"id": "user-1", "name": "Alice"}, "id": 1}

// Error response
{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": 1}

// Notification (no id = no response)
{"jsonrpc": "2.0", "method": "logs.notify", "params": {"level": "info"}}

Auto-Expose Routes

Automatically converts Forge HTTP routes into JSON-RPC methods. Each route's handler is invoked via the router, preserving all middleware:

// HTTP route: POST /users -> JSON-RPC method: create.users
// HTTP route: GET /users/:id -> JSON-RPC method: get.users
// HTTP route: PUT /users/:id -> JSON-RPC method: update.users
// HTTP route: DELETE /users/:id -> JSON-RPC method: delete.users

orpc.NewExtension(
    orpc.WithAutoExposeRoutes(true),
    orpc.WithMethodPrefix("myapp."), // prefix all methods
)

Manual Method Registration

Register custom methods with explicit parameter and result schemas:

server.RegisterMethod(&orpc.Method{
    Name:        "math.add",
    Description: "Add two numbers",
    Params: &orpc.ParamsSchema{
        Type: "object",
        Properties: map[string]orpc.PropertySchema{
            "a": {Type: "number", Description: "First number"},
            "b": {Type: "number", Description: "Second number"},
        },
        Required: []string{"a", "b"},
    },
    Result: &orpc.ResultSchema{
        Type:        "object",
        Description: "Sum result",
    },
    Handler: func(ctx any, params any) (any, error) {
        p := params.(map[string]any)
        return map[string]any{"sum": p["a"].(float64) + p["b"].(float64)}, nil
    },
})

OpenRPC Schema

Automatically generates a machine-readable OpenRPC document describing all methods, parameters, and result schemas. Available at the schema endpoint (default /rpc/schema):

doc := server.OpenRPCDocument()
// Returns full OpenRPCDocument with info, methods, schemas

Schemas are extracted from route metadata and method definitions.

Batch Requests

Process multiple JSON-RPC calls in a single HTTP request:

[
    {"jsonrpc": "2.0", "method": "users.get", "params": {"id": "1"}, "id": 1},
    {"jsonrpc": "2.0", "method": "users.get", "params": {"id": "2"}, "id": 2},
    {"jsonrpc": "2.0", "method": "users.get", "params": {"id": "3"}, "id": 3}
]

Configurable batch size limit via BatchLimit (default: 10). Returns ErrBatchTooLarge when exceeded.

Naming Strategies

Choose how routes are converted to method names:

StrategyExample RouteMethod Name
path (default)POST /userscreate.users
methodPOST /usersPOST_users
customvia route metadataorpc.method value

Override individual method names via route metadata:

app.Router().POST("/users", handler,
    forge.WithMetadata("orpc.method", "registerUser"),
)

Include/Exclude Patterns

Control which routes are exposed with glob-style patterns:

orpc.NewExtension(
    orpc.WithAutoExposeRoutes(true),
    orpc.WithIncludePatterns("/api/*"),
    orpc.WithExcludePatterns("/_/*", "/internal/*"),
)

Default exclude: ["/_/*"] (skips internal Forge endpoints).

Interceptor Pipeline

Chain interceptors on the oRPC server for cross-cutting concerns:

server.Use(func(ctx context.Context, req *orpc.Request, next orpc.MethodHandler) (any, error) {
    // Validate, log, authorize, etc.
    start := time.Now()
    result, err := next(ctx, req.Params)
    log.Printf("[oRPC] %s took %v", req.Method, time.Since(start))
    return result, err
})

Authentication and Rate Limiting

  • Token auth -- optional header-based authentication (AuthHeader, AuthTokens)
  • Rate limiting -- configurable per-minute rate limit (RateLimitPerMinute)
  • Request size -- reject oversized requests (MaxRequestSize, default 1 MB)
  • Request timeout -- per-request timeout (RequestTimeout, default 30 seconds)

Server Statistics

Track method counts and request metrics:

stats := server.GetStats()
fmt.Printf("Methods: %d, Requests: %d, Errors: %d, Avg latency: %v\n",
    stats.TotalMethods, stats.TotalRequests, stats.TotalErrors, stats.AverageLatency)

JSON-RPC Error Codes

CodeConstantMeaning
-32700ErrParseErrorInvalid JSON
-32600ErrInvalidRequestMalformed JSON-RPC
-32601ErrMethodNotFoundMethod not found
-32602ErrInvalidParamsInvalid parameters
-32603ErrInternalErrorInternal server error
-32000ErrServerErrorGeneric server error

Sentinel Errors

ErrorMeaning
ErrMethodExistsMethod name already registered
ErrMethodNotFoundErrorMethod name not found
ErrInvalidMethodNameMethod name is empty or invalid
ErrDisabledoRPC extension is disabled
ErrBatchDisabledBatch requests are disabled
ErrBatchTooLargeBatch exceeds BatchLimit
ErrRequestTooLargeRequest exceeds MaxRequestSize

How is this guide?

On this page