Search code examples
javajsonprotocol-buffersgrpcbazel

gRPC + Bazel + Envoy Json Proxy - How to import google/api/annotations.proto


I have a very simple gRPC Service defined as:

syntax = "proto3";
package helloworld;
import "annotations.proto";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello(HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      post: "/api/v1/hello"
      body: "*"
    }
  }
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

The interesting aspect is that I'm using the Envoy gRPC <> JSON transcoding filter to "translate" between HTTP2/Protobuf <> HTTP1/JSON. See https://www.envoyproxy.io/docs/envoy/latest/api-v1/http_filters/grpc_json_transcoder_filter for more details.

Further, I'm using Bazel to build the Java based gRPC Services. The Envoy transcoding filter requires some annotations:

option (google.api.http) = {
  post: "/api/v1/hello"
  body: "*"
}

I'm using the proto_library (https://github.com/cgrushko/proto_library) to generate the corresponding .java files from the .proto definitions, but I'm not able to add the

import "google/api/annotations.proto";

to the .proto files, as I have no idea how to import https://github.com/googleapis/googleapis/blob/master/google/api/annotations.proto to a bazel project.

Thank you.

Best Regards, jj


Solution

  • The ugly, unmaintainable super-fast way: vendor the file

    You can usually copy a .proto to your own project and build against it; as long as the upstream proto doesn't change "too much" it will continue working.

    If, for example, googleapi surveys who's using their repo, they won't find your usage if you copied the file.

    Once you have the file in your repo you can follow the example in https://github.com/cgrushko/proto_library/blob/04369f0d2ade8c8566727e0b6f3a53f1ba8925c0/src/BUILD.

    The maintainable way: external repository

    An external repository (e.g. http_archive) allows you to depend on another Bazel project. With http_archive, it will be downloaded and built as part of your build.

    With http_archive, the external project must already build with Bazel, which is not exactly the case for googleapi: it doesn't have a BUILD file for google/api/annotations.proto.

    One option is to talk with them and see if they can add such a BUILD file (or send a PR yourself). The other option is to use new_http_archive and provide your own BUILD file as part of the definition.

    Adding the following to your WORKSPACE file (at the root of your project) should work more or less:

    new_http_archive(
      name = "googleapi",
      url = "https://github.com/googleapis/googleapis/archive/common-protos-1_3_1.zip",
      strip_prefix = "googleapis-common-protos-1_3_1/",
      build_file_content = "proto_library(name = 'annotations_proto', srcs = ['google/api/annotations.proto'])"
    )
    

    Then, you'd be able to depend on it your code:

    proto_library(
      name = "hellow_world_proto",
      ...
      deps = ["@googleapi//:annotations_proto"],
    )