Implementation of a protocol conversion gateway, corresponding to the github project github.com/grpc-ecosys… The gateway is responsible for receiving the client request and then deciding whether to forward it directly to the GRPC service or to the HTTP service. Of course, the HTTP service also needs to request the GRPC service for the response and then turn it into a JSON response to the client. The structure is shown as follows:

Installation tools

$ go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
Copy the code

The directory structure

├ ─ grpcgateway │ ├ ─ echohttp │ │ ├ ─ client │ │ │ main. Go │ │ │ │ │ ├ ─ server │ │ │ main. Go │ │ │ │ │ └ ─ server_http │ │ Main. Go │ │ │ └ ─ protos │ ├ ─ echo │ │ service. The pb. Go │ │ service. The pb. Gw go │ │ service. The proto │ │ service_grpc. Pb. Go │ │ │ └─ Google │ ├ ─ garbage, ├ ─ API │ annotationsCopy the code

demo

$ cd protos
Copy the code

Annotations. Proto and http.proto from github.com/googleapis/… Copy to local

2.echo/service.proto:

syntax = "proto3"; option go_package = "./echo"; package echo; import "google/api/annotations.proto"; service EchoService { rpc Echo(EchoMessage) returns (EchoMessage) { option (google.api.http) = { post: "/v1/echo" body: "*"}; } } message EchoMessage { string value = 1; }Copy the code

3. The compiler proto

Compile the Google API

$ protoc -I . --go_out=paths=source_relative:. --go_opt=Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor:.  google/api/*.proto
Copy the code

Compile the echo. Proto

$ protoc -I . --go_out=. --go_opt=Mgoogle/api/annotations.proto=./google/api:. --go-grpc_out=. --go-grpc_opt=Mgoogle/api/annotations.proto=./google/api:. echo/*.proto
Copy the code

Compile the echo. Proto gateway

$ protoc --grpc-gateway_out=logtostderr=true:. echo/*.proto
Copy the code

4. Implement the server and client server/main.go

package main import ( "fmt" "net" pb "zpool/grpcgateway/protos/echo" "golang.org/x/net/context" "google.golang.org/grpc" "Google.golang.org/grpc/grpclog") const (Address = "127.0.0.1:50052)" type the echoService struct { pb.UnimplementedEchoServiceServer } func (*echoService) Echo(ctx context.Context, in *pb.EchoMessage) (*pb.EchoMessage, error) { return &pb.EchoMessage{ Value: in.Value, }, nil } func main() { listen, err := net.Listen("tcp", Address) if err ! = nil { grpclog.Fatalf("Failed to listen: % v ", err)} / / instantiate GRPC Server s: = GRPC. NewServer () / / registered the echoService pb. RegisterEchoServiceServer (s, &echoService{}) fmt.Println("Listen on " + Address) s.Serve(listen) }Copy the code

client/main.go

package main import ( "fmt" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" pb "The zpool grpcgateway/protos/echo") const (Address = "127.0.0.1:50052") func main () {/ / connect the conn, err := grpc.Dial(Address, grpc.WithInsecure()) if err ! = nil {grpClog.fatalln (err)} defer conn.close () // Initialize the client c := pb.newEchoServiceclient (conn) // call method req := &pb.EchoMessage{Value: "gRPC"} res, err := c.Echo(context.Background(), req) if err ! = nil { grpclog.Fatalln(err) } fmt.Println(res.Value) }Copy the code

5.server_http/main.go

package main import ( "fmt" "net/http" "github.com/grpc-ecosystem/grpc-gateway/runtime" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" gw "zpool/grpcgateway/protos/echo" ) func main() { ctx := context.Background() ctx, // GRPC service address endpoint := "127.0.0.1:50052" mux := runtime.newServemux () Opts: [] = GRPC. DialOption {GRPC. WithInsecure ()} / / HTTP GRPC err: = gw RegisterEchoServiceHandlerFromEndpoint (CTX, mux. endpoint, opts) if err ! = nil { grpclog.Fatalf("Register handler err:%v\n", err) } fmt.Println("HTTP Listen on 8080") http.ListenAndServe(":8080", mux) }Copy the code

6.Test

GRPC request:

go run server/main.go
go run client/main.go
Copy the code

The HTTP request:

go run server/main.go go run server_http/main.go curl -X POST -k http://localhost:8080/v1/echo -d '{"value": "gRPC-HTTP is working!" } 'Copy the code