I love using protobuf and the grpc-gateway plugin to generate a reverse proxy so that I can expose my APIs
both via plain gRPC
and HTTP.
But since everything in gRPC
is statically typed due to its dependency on protobuf
definitions, things can get
a little tricky when we can’t handle the structure of the incoming payload.
I recently stumbled on this issue. I needed to expose a webhook endpoint so that external services (DocuSign in this case) could call the endpoint to notify my system of any updates. The problem is that I don’t control DocuSign’s payload, so I need to have a generic field in my message to which the gateway can bind the incoming data.
Roger Chapman has a very detailed post on how to bind the incoming raw body to a byte array.
If you don’t know anything about the incoming data then Roger’s approach is probably your best bet. But if the data you’re expecting is JSON then using a protobuf struct field will do the trick as I show below:
message WebhookRequest {
google.protobuf.Struct body = 1;
}
service WebhookService {
rpc Webhook(WehookRequest) returns(google.protobuf.Empty) {
option (google.api.http) = {
post: "webhook"
body: "body"
};
}
}
The trick is to tell the grpc-gateway
plugin to bind all the body of the request to the body
field of
our WebhookRequest
message. Since the incoming raw body is JSON the default marshaller will be able to correctly
bind the incoming data to the google.protobuf.struct
without further changes or middlewares.