Stream RPC
starpc implements Proto3 services (server & client) in both TypeScript and Go.
Supports client-to-server streaming RPCs in the web browser, currently not
supported by any of the major RPC libraries.
The rpcproto file describes the protocol.
Can use any Stream multiplexer: defaults to libp2p-mplex over a WebSocket.
rpcstream supports sub-streams for per-component sub-services.
Usage
Starting with the protobuf-project repository on the "starpc" branch.
Use "git add" to add your new .proto files, then yarn gen
to generate the
TypeScript and Go code for them.
Examples
See the protobuf-project template on the "starpc" branch.
The demo/boilerplate project implements the Echo example below.
This repository uses protowrap, see the Makefile.
Protobuf
The following examples use the echo protobuf sample.
syntax = "proto3";
package echo;
// Echoer service returns the given message.
service Echoer {
// Echo returns the given message.
rpc Echo(EchoMsg) returns (EchoMsg);
// EchoServerStream is an example of a server -> client one-way stream.
rpc EchoServerStream(EchoMsg) returns (stream EchoMsg);
// EchoClientStream is an example of client->server one-way stream.
rpc EchoClientStream(stream EchoMsg) returns (EchoMsg);
// EchoBidiStream is an example of a two-way stream.
rpc EchoBidiStream(stream EchoMsg) returns (stream EchoMsg);
}
// EchoMsg is the message body for Echo.
message EchoMsg {
string body = 1;
}
Go
This example demonstrates both the server and client:
// construct the server
echoServer := &echo.EchoServer{}
mux := srpc.NewMux()
if err := echo.SRPCRegisterEchoer(mux, echoServer); err != nil {
t.Fatal(err.Error())
}
server := srpc.NewServer(mux)
// create an in-memory connection to the server
openStream := srpc.NewServerPipe(server)
// construct the client
client := srpc.NewClient(openStream)
// construct the client rpc interface
clientEcho := echo.NewSRPCEchoerClient(client)
ctx := context.Background()
bodyTxt := "hello world"
out, err := clientEcho.Echo(ctx, &echo.EchoMsg{
Body: bodyTxt,
})
if err != nil {
t.Fatal(err.Error())
}
if out.GetBody() != bodyTxt {
t.Fatalf("expected %q got %q", bodyTxt, out.GetBody())
}
TypeScript
See the ts-proto README to generate the TypeScript for your protobufs.
For an example of Go <-> TypeScript interop, see the integration test. For an
example of TypeScript <-> TypeScript interop, see the e2e test.
Supports any AsyncIterable communication channel. DuplexConn
,
MessagePortConn
, and WebSocketConn
use js-libp2p-mplex to multiplex
streams, but any multiplexer can be used.
This example demonstrates both the server and client:
import { pipe } from 'it-pipe'
import { createHandler, createMux, Server, Client, Conn } from 'srpc'
import { EchoerDefinition, EchoerServer, runClientTest } from 'srpc/echo'
const mux = createMux()
const echoer = new EchoerServer()
mux.register(createHandler(EchoerDefinition, echoer))
const server = new Server(mux)
const clientConn = new Conn()
const serverConn = new Conn(server)
pipe(clientConn, serverConn, clientConn)
const client = new Client(clientConn.buildOpenStreamFunc())
console.log('Calling Echo: unary call...')
let result = await demoServiceClient.Echo({
body: 'Hello world!',
})
console.log('success: output', result.body)
const clientRequestStream = new Observable<EchoMsg>(subscriber => {
subscriber.next({body: 'Hello world from streaming request.'})
subscriber.complete()
})
console.log('Calling EchoClientStream: client -> server...')
result = await demoServiceClient.EchoClientStream(clientRequestStream)
console.log('success: output', result.body)
WebSocket
One way to integrate Go and TypeScript is over a WebSocket:
import { WebSocketConn } from 'srpc'
import { EchoerClientImpl } from 'srpc/echo'
const ws = new WebSocket('ws://localhost:5000/demo')
const channel = new WebSocketConn(ws)
const client = channel.buildClient()
const demoServiceClient = new EchoerClientImpl(client)
const result = await demoServiceClient.Echo({
body: "Hello world!"
})
console.log('output', result.body)
Attribution
protoc-gen-go-starpc
is a heavily modified version of protoc-gen-go-drpc
.
Be sure to check out drpc as well: it's compatible with grpc, twirp, and more.
Uses vtprotobuf to generate Protobuf marshal / unmarshal code.
Support
Starpc is built & supported by Aperture Robotics, LLC.
Community contributions and discussion are welcomed!
Please open a GitHub issue with any questions / issues.
... or feel free to reach out on Matrix Chat or Discord.