A PoC to derive REST services from GRPC specifications
Clone or download

README.md

Build status Dependencies License GRPCGatewayGenerator GRPCGatewayRuntime

GRPC Gateway

Automatically derive REST services from GRPC specifications.

Principle

GRPCGateway is inspired by the GRPCGateway originally developed in Go. It creates a Proxy forwarding REST calls to GRPC services.

Installation

You need to enable sbt-protoc plugin to generate source code for the proto definitions. You can do it by adding a protoc.sbt file into your project folder with the following lines:

addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.17")

resolvers += Resolver.bintrayRepo("beyondthelines", "maven")

libraryDependencies ++= Seq(
  "com.trueaccord.scalapb" %% "compilerplugin" % "0.7.0",
  "beyondthelines"         %% "grpcgatewaygenerator" % "0.0.9"
)

Here we add a dependency to the protobuf generator for the gRPC gateway in order to be able to generate REST services and Swagger documentation.

Then we need to trigger the generation from the build.sbt:

PB.targets in Compile := Seq(
  // compile your proto files into scala source files
  scalapb.gen() -> (sourceManaged in Compile).value,
  // generate Swagger spec files into the `resources/specs`
  grpcgateway.generators.SwaggerGenerator -> (resourceDirectory in Compile).value / "specs",
  // generate the Rest Gateway source code
  grpcgateway.generators.GatewayGenerator -> (sourceManaged in Compile).value
)

resolvers += Resolver.bintrayRepo("beyondthelines", "maven")

libraryDependencies += "beyondthelines" %% "grpcgatewayruntime" % "0.0.9" % "compile,protobuf"

Usage

You're now ready to create your GRPC gateway.

First thing is to annotate the proto files to define the REST endpoints:

import "google/api/annotations.proto";

rpc GetFeature(Point) returns (Feature) {
  option (google.api.http) = {
    get: "/v1/example/feature"
  };
}

Then you need to create a GRPC channel pointing to your GRPC server:

val channel = 
  io.grpc.ManagedChannelBuilder
    .forAddress("localhost", 8980)
    .usePlaintext(true)
    .build()

and finally create the gateway itself:

val gateway = GrpcGatewayServerBuilder
    .forPort(8981)
    .addService(new RouteGuideHandler(channel))
    .build()
    

Here RouteGuideHandler is the handler automatically generated from the protobuf files.

You can use start() and shutdown() to start and shutdown the gateway.

gateway.start()

sys.addShutdownHook {
  gateway.shutdown()
}

API Documentation

A swagger spec for the supported services is automatically generated and served using swagger-ui.

Once the gateway is running you can point your browser to http://localhost:8981/docs/index.html?url=/specs/RouteGuideService.yml

where RouteGuideService.yml is the Swagger spec automatically generated from the protobuf files.

Limitations

Only GRPC Unary calls are supported (i.e. No streaming supported).