twitchtv/twirp を試した

github.com

gRPCのようなフレームワークで、違いはHTTP 1.1で動くこととJSONをサポートしてること。

インストール

protoc-gen-twirpの他にprotocとprotoc-gen-goも必要。

$ go get github.com/twitchtv/twirp/protoc-gen-twirp

$ brew install protobuf
$ go get github.com/golang/protobuf/protoc-gen-go

protoファイル

まずprotoファイルを書く。

$ mkdir proto
$ vi proto/hello.proto
syntax = "proto3";
package utahta.twirp.example.helloworld;
option go_package = "helloworld";

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

message HelloReq {
  string subject = 1;
}

message HelloResp {
  string test = 1;
}

protocする

protoファイルからgoファイルをつくる。

$ mkdir helloworld
$ protoc --proto_path=./proto --twirp_out=./helloworld --go_out=./helloworld ./proto/hello.proto
$ ls helloworld
hello.pb.go    hello.twirp.go

サーバを書く

$ mkdir server
$ vi server/main.go
package main

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

    "github.com/utahta/twirp-example/helloworld"
)

type Server struct{}

func (s *Server) Hello(ctx context.Context, req *helloworld.HelloReq) (*helloworld.HelloResp, error) {
    return &helloworld.HelloResp{
        Test: fmt.Sprintf("Subject: %s", req.Subject),
    }, nil
}

func main() {
    s := &Server{}
    handler := helloworld.NewHellowWorldServer(s, nil)
    http.ListenAndServe(":8881", handler)
}

クライアントを書く

$ mkdir client
$ vi client/main.go
package main

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

    "github.com/utahta/twirp-example/helloworld"
)

func main() {
    c := helloworld.NewHellowWorldProtobufClient("http://localhost:8881", http.DefaultClient)
    resp, err := c.Hello(context.Background(), &helloworld.HelloReq{Subject: "hello twirp"})
    if err != nil {
        panic(err)
    }
    fmt.Printf("%#v\n", resp)
}

最終的に次のようなディレクトリ構成になった。

.
├── client
│   └── main.go
├── helloworld
│   ├── hello.pb.go
│   └── hello.twirp.go
├── proto
│   └── hello.proto
└── server
    └── main.go

実行する

まずサーバを実行。

$ go run server/main.go

次にクライアントを実行する。 すると結果が返ってくる。

$ go run client/main.go
&helloworld.HelloResp{Test:"Subject: hello twirp"}

curlで実行する

JSONに対応しているのでcurlを使ってさくっとリクエストできる。

$ curl -H 'Content-Type:application/json' -X POST -d '{"subject":"hello curl"}' "http://127.0.0.1:8881/twirp/utahta.twirp.example.helloworld.HellowWorld/Hello"

雑感

シュッと書いたらProtocolBuffersとJSONで会話できるようになってすごい。便利。
学習コストの低さがなによりいい。