diff --git a/README.md b/README.md index ba06d64..02bf942 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,49 @@ type _ interface { ``` +### Custom Transport Feature +The go-jsonrpc library supports creating clients with custom transport mechanisms (e.g. use for IPC). This allows for greater flexibility in how requests are sent and received, enabling the use of custom protocols, special handling of requests, or integration with other systems. + +#### Example Usage of Custom Transport + +Here is an example demonstrating how to create a custom client with a custom transport mechanism: + +```go +// Setup server +serverHandler := &SimpleServerHandler{} // some type with methods + +rpcServer := jsonrpc.NewServer() +rpcServer.Register("SimpleServerHandler", serverHandler) + +// Custom doRequest function +doRequest := func(ctx context.Context, body []byte) (io.ReadCloser, error) { + reader := bytes.NewReader(body) + pr, pw := io.Pipe() + go func() { + defer pw.Close() + rpcServer.HandleRequest(ctx, reader, pw) // handle the rpc frame + }() + return pr, nil +} + +var client struct { + Add func(int) error +} + +// Create custom client +closer, err := jsonrpc.NewCustomClient("SimpleServerHandler", []interface{}{&client}, doRequest) +if err != nil { + log.Fatalf("Failed to create client: %v", err) +} +defer closer() + +// Use the client +if err := client.Add(10); err != nil { + log.Fatalf("Failed to call Add: %v", err) +} +fmt.Printf("Current value: %d\n", client.AddGet(5)) +``` + ## Contribute PRs are welcome! diff --git a/client.go b/client.go index 57d37d1..ba355ee 100644 --- a/client.go +++ b/client.go @@ -152,6 +152,10 @@ func NewCustomClient(namespace string, outs []interface{}, doRequest func(ctx co return clientResponse{}, xerrors.Errorf("marshalling request: %w", err) } + if ctx == nil { + ctx = context.Background() + } + rawResp, err := doRequest(ctx, b) if err != nil { return clientResponse{}, xerrors.Errorf("doRequest failed: %w", err) diff --git a/rpc_test.go b/rpc_test.go index f450849..14de65c 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -1,6 +1,7 @@ package jsonrpc import ( + "bytes" "context" "encoding/json" "errors" @@ -1651,3 +1652,43 @@ func TestBigResult(t *testing.T) { fmt.Println("done") } + +func TestNewCustomClient(t *testing.T) { + // Setup server + serverHandler := &SimpleServerHandler{} + rpcServer := NewServer() + rpcServer.Register("SimpleServerHandler", serverHandler) + + // Custom doRequest function + doRequest := func(ctx context.Context, body []byte) (io.ReadCloser, error) { + reader := bytes.NewReader(body) + pr, pw := io.Pipe() + go func() { + defer pw.Close() + rpcServer.HandleRequest(ctx, reader, pw) + }() + return pr, nil + } + + var client struct { + Add func(int) error + AddGet func(int) int + } + + // Create custom client + closer, err := NewCustomClient("SimpleServerHandler", []interface{}{&client}, doRequest) + require.NoError(t, err) + defer closer() + + // Add(int) error + require.NoError(t, client.Add(10)) + require.Equal(t, int32(10), serverHandler.n) + + err = client.Add(-3546) + require.EqualError(t, err, "test") + + // AddGet(int) int + n := client.AddGet(3) + require.Equal(t, 13, n) + require.Equal(t, int32(13), serverHandler.n) +}