oRPC
oRPC
JSON-RPC 2.0 server with OpenRPC schema generation and auto-route exposure
Overview
github.com/xraph/forge/extensions/orpc provides a JSON-RPC 2.0 server that can auto-expose Forge HTTP
routes as JSON-RPC methods. It registers an ORPCService in the DI container and mounts RPC endpoints
on the Forge HTTP router with optional OpenRPC schema generation, batch requests, and method discovery.
What It Registers
| Service | DI Key | Type |
|---|---|---|
| oRPC service | orpc | *ORPCService (also satisfies ORPC) |
Routes registered on the Forge HTTP router in Start():
POSTon the RPC endpoint (default/rpc) for JSON-RPC requestsGETon the schema endpoint (default/rpc/schema) for OpenRPC documentGETon/rpc/methodsfor method discovery (when enabled)
Quick Start
package main
import (
"context"
"github.com/xraph/forge"
"github.com/xraph/forge/extensions/orpc"
)
func main() {
app := forge.NewApp(forge.AppConfig{Name: "my-app", Version: "1.0.0"})
app.RegisterExtension(orpc.NewExtension(
orpc.WithEndpoint("/rpc"),
orpc.WithAutoExposeRoutes(true), // auto-expose Forge HTTP routes as JSON-RPC methods
orpc.WithOpenRPC(true),
orpc.WithBatch(true),
))
// Define some HTTP routes
app.Router().POST("/users", createUserHandler)
app.Router().GET("/users/:id", getUserHandler)
ctx := context.Background()
app.Start(ctx)
defer app.Stop(ctx)
// Routes are now available as JSON-RPC methods:
// POST /rpc -> {"jsonrpc":"2.0","method":"create.users","params":{"name":"Alice"},"id":1}
// POST /rpc -> {"jsonrpc":"2.0","method":"get.users","params":{"id":"123"},"id":2}
}Manual Method Registration
Register custom JSON-RPC methods directly:
svc, _ := forge.InjectType[*orpc.ORPCService](app.Container())
server := svc.Server()
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
},
})Adding Interceptors
Chain interceptors for cross-cutting concerns:
server.Use(func(ctx context.Context, req *orpc.Request, next orpc.MethodHandler) (any, error) {
start := time.Now()
result, err := next(ctx, req.Params)
log.Printf("Method %s took %v", req.Method, time.Since(start))
return result, err
})Batch Requests
Send multiple JSON-RPC calls in a single HTTP request:
[
{"jsonrpc":"2.0","method":"math.add","params":{"a":1,"b":2},"id":1},
{"jsonrpc":"2.0","method":"math.add","params":{"a":3,"b":4},"id":2}
]Batch size is limited by BatchLimit (default: 10).
Key Concepts
- Auto-expose routes -- when
AutoExposeRoutesis enabled, all Forge HTTP routes are automatically registered as JSON-RPC methods. The naming strategy converts paths to method names (e.g.POST /usersbecomescreate.users). - OpenRPC schema -- automatically generates an OpenRPC document describing all registered methods with parameter and result schemas.
- Batch requests -- JSON-RPC batch support with configurable batch size limits.
- Method naming -- choose from
path(default),method, orcustomnaming strategies. Add a prefix withMethodPrefix. - Route execution -- auto-exposed methods execute via the Forge router, preserving all middleware and handlers.
Important Runtime Notes
- Routes are exposed during
Start()after all extensions have registered their routes. - Exclude patterns default to
["/_/*"]to skip internal Forge endpoints. - Methods can also be registered manually via
ORPC.RegisterMethod(). - Rate limiting and auth can be enabled at the oRPC level independently from the main app.
Detailed Pages
How is this guide?