gRPC Gateway Webhooks

Updated: December 19, 2022 Reading Time: 2 minutes stage: in progress

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.