Download

Background

gRPC is great -- it generates API clients and server stubs in many programming languages, it is fast, easy-to-use, bandwidth-efficient and its design is combat-proven by Google. However, you might still want to provide a traditional RESTful API as well. Reasons can range from maintaining backwards-compatibility, supporting languages or clients not well supported by gRPC to simply maintaining the aesthetics and tooling involved with a RESTful architecture.

This project aims to provide that HTTP+JSON interface to your gRPC service. A small amount of configuration in your service to attach HTTP semantics is all that's needed to generate a reverse-proxy with this library.

Installation

First you need to install ProtocolBuffers 3.0.0 or later.

mkdir tmp

cd tmp

git clone https://github.com/protocolbuffers/protobuf

cd protobuf

./autogen.sh

./configure

make

make check

sudo make install

Then, go get -u as usual the following packages:

go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway

go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger

go get -u github.com/golang/protobuf/protoc-gen-go

Usage

Make sure that your $GOPATH/bin is in your $PATH.

  1. Define your service in gRPC

your_service.proto:

syntax = "proto3";

package example;

message StringMessage {

  string value = 1;

}

 

service YourService {

  rpc Echo(StringMessage) returns (StringMessage) {}

}

  1. Add a google.api.http
  2.  to your .proto file

your_service.proto:

 syntax = "proto3";

 package example;

+

+import "google/api/annotations.proto";

+

 message StringMessage {

   string value = 1;

 }

 

 service YourService {

-  rpc Echo(StringMessage) returns (StringMessage) {}

+  rpc Echo(StringMessage) returns (StringMessage) {

+    option (google.api.http) = {

+      post: "/v1/example/echo"

+      body: "*"

+    };

+  }

 }

If you do not want to modify the proto file for use with grpc-gateway you can alternatively use an external gRPC Service Configuration file. Check our documentation for more information.

  1. Generate gRPC stub

4.  protoc -I/usr/local/include -I. \

5.    -I$GOPATH/src \

6.    -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

7.    --go_out=plugins=grpc:. \

  path/to/your_service.proto

It will generate a stub file path/to/your_service.pb.go.

  1. Implement your service in gRPC as usual
    1. (Optional) Generate gRPC stub in the language you want.

e.g.

protoc -I/usr/local/include -I. \

  -I$GOPATH/src \

  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

  --ruby_out=. \

  path/to/your/service_proto

 

protoc -I/usr/local/include -I. \

  -I$GOPATH/src \

  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

  --plugin=protoc-gen-grpc=grpc_ruby_plugin \

  --grpc-ruby_out=. \

  path/to/your/service.proto

    1. Add the googleapis-common-protos gem (or your language equivalent) as a dependency to your project.
    2. Implement your service
  1. Generate reverse-proxy

10. protoc -I/usr/local/include -I. \

11.   -I$GOPATH/src \

12.   -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

13.   --grpc-gateway_out=logtostderr=true:. \

  path/to/your_service.proto

It will generate a reverse proxy path/to/your_service.pb.gw.go.

Note: After generating the code for each of the stubs, in order to build the code, you will want to run go get . from the directory containing the stubs.

  1. Write an entrypoint

Now you need to write an entrypoint of the proxy server.

package main

 

import (

  "flag"

  "net/http"

 

  "github.com/golang/glog"

  "golang.org/x/net/context"

  "github.com/grpc-ecosystem/grpc-gateway/runtime"

  "google.golang.org/grpc"

 

  gw "path/to/your_service_package"

)

 

var (

  echoEndpoint = flag.String("echo_endpoint", "localhost:9090", "endpoint of YourService")

)

 

func run() error {

  ctx := context.Background()

  ctx, cancel := context.WithCancel(ctx)

  defer cancel()

 

  mux := runtime.NewServeMux()

  opts := []grpc.DialOption{grpc.WithInsecure()}

  err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts)

  if err != nil {

    return err

  }

 

  return http.ListenAndServe(":8080", mux)

}

 

func main() {

  flag.Parse()

  defer glog.Flush()

 

  if err := run(); err != nil {

    glog.Fatal(err)

  }

}

  1. (Optional) Generate swagger definitions

16. protoc -I/usr/local/include -I. \

17.   -I$GOPATH/src \

18.   -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

19.   --swagger_out=logtostderr=true:. \

  path/to/your_service.proto