GitHub - chai2010/pbgo-grpc: pbgo grpc/rest examples (original) (raw)
- Go语言QQ群: 102319854, 1055927514
- 凹语言(凹读音“Wa”)(The Wa Programming Language): https://github.com/wa-lang/wa
pbgo-examples
Proto File(hello.proto)
syntax = "proto3";
package hello_pb;
import "github.com/chai2010/pbgo/pbgo.proto";
message String { string value = 1; } message StaticFile { string content_type = 1; bytes content_body = 2; }
message Message { string value = 1; repeated int32 array = 2; map<string,string> dict = 3; String subfiled = 4; }
service HelloService { option (pbgo.service_opt) = { rename: "PBGOHelloService" };
rpc Hello (String) returns (String) {
option (pbgo.rest_api) = {
get: "/hello/:value"
post: "/hello"
additional_bindings {
method: "DELETE"; url: "/hello"
}
additional_bindings {
method: "PATCH"; url: "/hello"
}
};
}
rpc Echo (Message) returns (Message) {
option (pbgo.rest_api) = {
get: "/echo/:subfiled.value"
};
}
rpc Static(String) returns (StaticFile) {
option (pbgo.rest_api) = {
additional_bindings {
method: "GET"
url: "/static/:value"
content_type: ":content_type"
content_body: ":content_body"
}
};
}
rpc ServerStream(String) returns (stream String);
rpc ClientStream(stream String) returns (String);
rpc Channel(stream String) returns (stream String);}
Generate stub code:
$ go install github.com/chai2010/pbgo-grpc/protoc-gen-pbgo-grpc
$ protoc -I=. -I=./api/third_party --pbgo-grpc_out=plugins=grpc+pbgo:. hello.proto
Example
package main
import ( "context" "errors" "flag" "io/ioutil" "log" "mime" "net" "net/http" "time"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection"
ctxpkg "github.com/chai2010/pbgo-grpc/context"
pb "github.com/chai2010/pbgo-grpc/example/api")
var ( _ pb.HelloServiceServer = (*HelloService)(nil) )
var ( flagRoot = flag.String("root", "./testdata", "set root dir") )
func init() { log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) }
func main() { flag.Parse()
helloService := NewHelloService(*flagRoot)
go func() {
grpcServer := grpc.NewServer()
reflection.Register(grpcServer)
pb.RegisterHelloServiceServer(grpcServer, helloService)
log.Println("grpc server on :3999")
lis, err := net.Listen("tcp", ":3999")
if err != nil {
log.Fatal(err)
}
grpcServer.Serve(lis)
}()
ctx := context.Background()
router := pb.PBGOHelloServiceGrpcHandler(
ctx, helloService,
func(ctx context.Context, req *http.Request) (context.Context, error) {
if methodName == "HelloService.Echo" {
return ctxpkg.AnnotateOutgoingContext(ctx, req, nil)
} else {
return ctxpkg.AnnotateIncomingContext(ctx, req, nil)
}
},
)
log.Println("http server on :8080")
log.Fatal(http.ListenAndServe(":8080", someMiddleware(router)))}
func someMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(wr http.ResponseWriter, r *http.Request) { timeStart := time.Now() defer func() { timeElapsed := time.Since(timeStart) log.Println(r.Method, r.URL, timeElapsed) }()
next.ServeHTTP(wr, r)
})}
type HelloService struct { rootdir string }
func NewHelloService(rootdir string) *HelloService { return &HelloService{ rootdir: rootdir, } }
func (p *HelloService) Hello(ctx context.Context, req *pb.String) (*pb.String, error) { log.Printf("HelloService.Hello: req = %v\n", req)
// curl -H "Grpc-Metadata-user-id: chai2010" localhost:8080/hello/gopher
// curl -H "Grpc-Metadata-user-password-Bin: MTIzNDU2" localhost:8080/hello/gopher
// base64("123456"): MTIzNDU2
if md, ok := metadata.FromIncomingContext(ctx); ok {
log.Printf("metadata.user-id: %v\n", md["user-id"])
log.Printf("metadata.user-password-bin: %v\n", md["user-password-bin"])
} else {
log.Println("no metadata")
}
reply := &pb.String{Value: "hello:" + req.GetValue()}
return reply, nil}
func (p *HelloService) Echo(ctx context.Context, req *pb.Message) (*pb.Message, error) { log.Printf("HelloService.Echo: req = %v\n", req)
// curl -H "Grpc-Metadata-user-id: chai2010" localhost:8080/echo/gopher
// curl -H "Grpc-Metadata-user-password-Bin: MTIzNDU2" localhost:8080/echo/gopher
// base64("123456"): MTIzNDU2
conn, err := grpc.Dial("localhost:3999", grpc.WithInsecure())
if err != nil {
log.Println(err)
return nil, err
}
defer conn.Close()
client := pb.NewHelloServiceClient(conn)
result, err := client.Hello(ctx, &pb.String{Value: "hello"})
if err != nil {
log.Println(err)
return nil, err
}
reply := &pb.Message{
Value: result.GetValue(),
}
return reply, nil}
func (p *HelloService) Static(ctx context.Context, req *pb.String) (*pb.StaticFile, error) { log.Printf("HelloService.Static: req = %v\n", req)
data, err := ioutil.ReadFile(p.rootdir + "/" + req.Value)
if err != nil {
return nil, err
}
reply := new(pb.StaticFile)
reply.ContentType = mime.TypeByExtension(req.Value)
reply.ContentBody = data
return reply, nil}
func (p *HelloService) ServerStream(*pb.String, pb.HelloService_ServerStreamServer) error { log.Printf("HelloService.ServerStream: todo\n")
return errors.New("todo")}
func (p *HelloService) ClientStream(pb.HelloService_ClientStreamServer) error { log.Printf("HelloService.ClientStream: todo\n")
return errors.New("todo")}
func (p *HelloService) Channel(pb.HelloService_ChannelServer) error { log.Printf("HelloService.Channel: todo\n")
return errors.New("todo")}
Start gRPC & Rest server:
Rest API:
$ curl localhost:8080/hello/gopher
{"value":"hello:gopher"}
$ curl localhost:8080/hello/gopher?value=vgo
{"value":"hello:vgo"}
$ curl localhost:8080/hello -X POST --data '{"value":"cgo"}'
{"value":"hello:cgo"}
$ curl localhost:8080/echo/gopher
{"subfiled":{"value":"gopher"}}
$ curl "localhost:8080/echo/gopher?array=123&array=456"
{"array":[123,456],"subfiled":{"value":"gopher"}}
$ curl "localhost:8080/echo/gopher?dict%5Babc%5D=123"
{"dict":{"abc":"123"},"subfiled":{"value":"gopher"}}
$ curl localhost:8080/static/gopher.png
$ curl localhost:8080/static/hello.txt
gRPC Context:
$ curl -H "Grpc-Metadata-user-id: chai2010" localhost:8080/hello/gopher
$ curl -H "Grpc-Metadata-user-password-Bin: MTIzNDU2" localhost:8080/hello/gopher
$ curl -H "Grpc-Metadata-user-id: chai2010" localhost:8080/echo/gopher
$ curl -H "Grpc-Metadata-user-password-Bin: MTIzNDU2" localhost:8080/echo/gopher
gRPC API:
$ grpcurl -plaintext localhost:3999 list
BUGS
Report bugs to chaishushan@gmail.com.
Thanks!