[Tutorial, Part 2] How to develop Go gRPC microservice with HTTP/REST endpoint, middleware, Kubernetes deployment, etc.
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!