[Tutorial, Part 2] How to develop Go gRPC microservice with HTTP/REST endpoint, middleware, Kubernetes deployment, etc.

Aleksandr Sokolovskii
4 min readSep 15, 2018

--

This is the continuation of the Part 1. The result of previous part is gRPC service and client. This part is dedicated to how to add HTTP/REST endpoint to the gRPC service. You can find full source code for Part 2 here.

To add HTTP/REST endpoint we are going to use cool grpc-gateway library. There is great article is describing in details how grpc-gateway works:

Step 1: Add REST annotation to API definition

First of all we have to install grpc-gateway and swagger documentation generator plugin:

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

grpc-gateway is installed to “%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway” folder.

We need to take proto includes from the grpc-gateway bundle:

Copy content of “%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google” folder to “third_party/google” folder in the project.

Create “protoc-gen-swagger/options” folder in the third_party project folder :

mkdir -p third_party\protoc-gen-swagger\options

then copy annotations.proto and openapiv2.proto files from “%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options” folder to “third_party\protoc-gen-swagger/options” folder in the project.

The result project structure should looks like this:

Before we continue we assume the Go language code generator plugin for Proto compiler is already installed. Run the following to ensure:

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

Next we have to add REST annotations (see details here) to the api/proto/v1/todo-service.proto file for ToDo service:

You can read more about Swagger annotation in proto file here.

Then create “api/swagger/v1” folder (the output location for generated swagger files) in the root of project:

mkdir -p api\swagger\v1

and replace content of third_party/protoc-gen.cmd file by the following:

Ensure we are in go-grpc-http-rest-microservice-tutorial folder and run compilation:

.\third_party\protoc-gen.cmd

It updates “pkg/api/v1/todo-service.pb.go” file and creates two new files:

  • pkg\api\v1\todo-service.pb.gw.go — REST/HTTP generated stub
  • api\swagger\v1\todo-service.swagger.json — generated Swagger documentation

The result project structure should looks like this:

Done. We have added REST annotation to API definition.

Step 2: Create HTTP gateway startup

Create server.go file in the “pkg/protocol/rest” folder with the following content:

You have to configure HTTPS for gateway in real life. See example how to do it.

Then update “pkg/cmd/server.go” file to start HTTP gateway:

You have to know that HTTP gateway is wrapper for gRPC service. My tests show about 1–3 milliseconds overhead.

The result project structure should looks like this:

Done.

Step 3: Create HTTP/REST client

Create “cmd/client-rest/main.go” file with the following content:

That’s all on client side. Result project structure should look like this:

The last step is to ensure that HTTP/REST gateway works.

Start terminal to build and run gRPC server with HTTP/REST gateway (replace parameters according to your SQL database server):

cd cmd/servergo build .server.exe -grpc-port=9090 -http-port=8080 -db-host=<HOST>:3306 -db-user=<USER> -db-password=<PASSWORD> -db-schema=<SCHEMA>

If we see:

2018/09/15 21:08:21 starting HTTP/REST gateway...
2018/09/09 08:02:16 starting gRPC server...

It means server is started. Open another terminal to build and run HTTP/REST client:

cd cmd/client-restgo build .client-rest.exe -server=http://localhost:8080

If we see something like this:

2018/09/15 21:10:05 Create response: Code=200, Body={"api":"v1","id":"24"}2018/09/15 21:10:05 Read response: Code=200, Body={"api":"v1","toDo":{"id":"24","title":"title (2018-09-15T18:10:05.3600923Z)","description":"description (2018-09-15T18:10:05.3600923Z)","reminder":"2018-09-15T18:10:05Z"}}2018/09/15 21:10:05 Update response: Code=200, Body={"api":"v1","updated":"1"}2018/09/15 21:10:05 ReadAll response: Code=200, Body={"api":"v1","toDos":[{"id":"24","title":"title (2018-09-15T18:10:05.3600923Z) + updated","description":"description (2018-09-15T18:10:05.3600923Z) + updated","reminder":"2018-09-15T18:10:05Z"}]
}
2018/09/15 21:10:05 Delete response: Code=200, Body={"api":"v1","deleted":"1"}

Everything works fine.

Resume for Part 2

That’s all for Part 2. We have developed HTTP/REST gateway for gRPC service and HTTP/REST client.

Source code for Part 2 is available here.

Part 3 is about how to add middleware (e.g. logging/tracing) to gRPC service and HTTP/REST endpoint as well.

Thanks!

--

--