Calling gRPC from REST with grpc-gateway
Overview of grpc-gateway Architecture
Using grpc-gateway, you can generate files for both gRPC and grpc-gateway from a single .proto file. This setup enables grpc-gateway to handle RESTful API requests and forward them to the gRPC server.
As stated in the https://github.com/grpc-ecosystem/grpc-gateway#about
Defining the .proto File
In addition to the usual gRPC definitions, you must specify how each REST endpoint maps to its corresponding gRPC RPC method.
syntax = "proto3";
import "google/api/annotations.proto";
package proto;
option go_package = "github.com/sanoyo/mini-lens-go/proto";
service HealthService {
rpc GetStatus(Empty) returns (AliveResponse) {
option (google.api.http) = {
get: "/health" // Endpoint configuration
};
}
}
message Empty {}
message AliveResponse {
bool status = 1;
}
The imported files like annotations.proto must be included in your project. You can either copy them manually or include them as a submodule. The README suggests copying the following files into your project:
- google/api/annotations.proto
- google/api/field_behaviour.proto
- google/api/http.proto
- google/api/httpbody.proto
Generating Files from the .proto File
For gRPC:
protoc -I . \
--go_out ./ \
--go_opt paths=source_relative \
--go-grpc_out ./ \
--go-grpc_opt paths=source_relative \
proto/health.proto
For grpc-gateway:
protoc -I . \
--grpc-gateway_out ./ \
--grpc-gateway_opt logtostderr=true \
--grpc-gateway_opt paths=source_relative \
--grpc-gateway_opt generate_unbound_methods=true \
proto/health.proto
Implementation Highlights
Server-Side:
The server must include a struct that embeds the UnimplementedHealthServiceServer to satisfy the gRPC server interface.
type healthServiceClient struct {
// Required addition
pb.UnimplementedHealthServiceServer
}
...
s := grpc.NewServer()
pb.RegisterHealthServiceServer(s, &healthServiceClient{})
Gateway-Side:
The …FromEndpoint method is used to initialize and start the gateway server.
err := pb.RegisterHealthServiceHandlerFromEndpoint(ctx, mux, endpoint, dialOpts)
if err != nil {
return nil, err
}
return http.ListenAndServe(address, mux)
Verifying the Setup
You can test the gateway server using a simple curl command:
curl http://localhost:3000/health
Reference
Deploying on GCP
On Google Cloud Platform (GCP), you can achieve similar functionality using Cloud Endpoints, which integrates grpc-gateway-like features. This can be configured either in the .proto file or using a YAML file.