Skip to content

Latest commit

 

History

History
124 lines (95 loc) · 3.52 KB

intro.md

File metadata and controls

124 lines (95 loc) · 3.52 KB
id title sidebar_label
intro
Meet Twirp!
Overview

Twirp is a simple RPC framework built on protobuf. You define a service in a .proto specification file, then Twirp will generate servers and clients for that service. It's your job to fill in the "business logic" that powers the server, and then generated clients can consume your service straight away.

This doc is an overview of how you use Twirp - how you interact with it, what you write, and what it generates. Using the Go implementation as example: https://github.com/twitchtv/twirp

Making a Twirp Service in Go

To make a Twirp service:

  1. Define your service in a Proto file.
  2. Use the protoc command to generate go code from the Proto file, it will generate an interface, a client and some server utils (to easily start an http listener).
  3. Implement the generated interface to implement the service.

For example, a HelloWorld Proto file:

syntax = "proto3";
package example.com.my.package.helloworld;
option go_package = "example.com/my/package/helloworld";

service HelloWorld {
  rpc Hello(HelloReq) returns (HelloResp);
}

message HelloReq {
  string subject = 1;
}

message HelloResp {
  string text = 1;
}

Running the protoc compiler with the --go_out and --twirp_out options will generate .pb.go and .twirp.go files. The Twirp file contains this interface:

type HelloWorld interface {
	Hello(context.Context, *HelloReq) (*HelloResp, error)
}

You provide the implementation:

package main

import (
	"context"
	"net/http"

	pb "github.com/twitchtv/twirp-example/rpc/helloworld"
)

type HelloWorldServer struct{}

func (s *HelloWorldServer) Hello(ctx context.Context, req *pb.HelloReq) (*pb.HelloResp, error) {
	return &pb.HelloResp{Text: "Hello " + req.Subject}, nil
}

// Run the implementation in a local server
func main() {
	twirpHandler := pb.NewHelloWorldServer(&HelloWorldServer{})
	// You can use any mux you like - NewHelloWorldServer gives you an http.Handler.
	mux := http.NewServeMux()
	// The generated code includes a method, PathPrefix(), which
	// can be used to mount your service on a mux.
	mux.Handle(twirpHandler.PathPrefix(), twirpHandler)
	http.ListenAndServe(":8080", mux)
}

And voila! Now you can use the auto-generated Client to make remote calls to your new service:

package main

import (
	"context"
	"fmt"
	"net/http"

	pb "github.com/twitchtv/twirp-example/rpc/helloworld"
)

func main() {
	client := pb.NewHelloWorldProtobufClient("http://localhost:8080", &http.Client{})

	resp, err := client.Hello(context.Background(), &pb.HelloReq{Subject: "World"})
	if err == nil {
		fmt.Println(resp.Text) // prints "Hello World"
	}
}

Why this is good

Twirp routing and serialization reduces the risk of introducing bugs. Both JSON and Protobuf are supported. The Protobuf protocol is designed to allow backwards compatible changes (unlike JSON, it is trivial to rename fields). Protobuf is super fast and the proto file definition also works well as documentation for your service.

What's next?

  • Install Twirp: instructions to install or upgrade Twirp tools for code auto-generation (protoc, protoc-gen-go and protoc-gen-twirp).
  • Usage Example: step by step guide to build an awesome Haberdasher service.
  • How Twirp routes requests: learn more about how Twirp works under the covers.