Version: v0.19.1 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2023 License: MIT


Stream RPC

GoDoc Widget Go Report Card Widget

Protobuf 3 RPC services over any stream multiplexer.


starpc implements Proto3 services (server & client) in both TypeScript and Go.

Supports client-to-server and bidirectional streaming in the web browser.

rpcproto.proto contains the protocol definition.

rpcstream supports sub-streams for per-component sub-services.


Start with the protobuf-project template repository on the "starpc" branch.

Use "git add" to add your new .proto files, then yarn gen to generate the TypeScript and Go code.


The demo/boilerplate project implements the Echo example below.

This repository uses protowrap, see the Makefile.


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;

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 {
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 {
if out.GetBody() != bodyTxt {
	t.Fatalf("expected %q got %q", bodyTxt, out.GetBody())

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.

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'
import { pushable } from 'it-pushable'

const mux = createMux()
const echoer = new EchoerServer()
mux.register(createHandler(EchoerDefinition, echoer))
const server = new Server(mux.lookupMethodFunc)

const clientConn = new Conn()
const serverConn = new Conn(server)
pipe(clientConn, serverConn, clientConn)
const client = new Client(clientConn.buildOpenStreamFunc())

// call the unary rpc
console.log('Calling Echo: unary call...')
let result = await demoServiceClient.Echo({
  body: 'Hello world!',
console.log('success: output', result.body)

// create a client -> server stream
const clientRequestStream = pushable<EchoMsg>({objectMode: true})
clientRequestStream.push({body: 'Hello world from streaming request.'})

// call the client -> server streaming rpc
console.log('Calling EchoClientStream: client -> server...')
result = await demoServiceClient.EchoClientStream(clientRequestStream)
console.log('success: output', result.body)

// call the server -> client streaming rpc
console.log('Calling EchoServerStream: server -> client...')
const serverStream = demoServiceClient.EchoServerStream({
  body: 'Hello world from server to client streaming request.',
for await (const msg of serverStream) {
  console.log('server: output', msg.body)

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)


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.


Please file a GitHub issue and/or Join Discord with any questions.

... or feel free to reach out on Matrix Chat.


Path Synopsis
hack module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL