GrpcReflection
View SourceServer reflection is a mechanism that allows servers to assist clients in runtime construction of requests by informing the client directly at runtime. No pre-shared schema is required.
According to the GRPC Server Reflection Protocol , the primary usecase for server reflection is to write (typically) command line debugging tools for talking to a grpc server. In particular, such a tool will take in a method and a payload (in human readable text format) send it to the server (typically in binary proto wire format), and then take the response and decode it to text to present to the user.
The GrpcReflection library adds reflection support to applications built with grpc-elixir.
Installation
The package can be installed by adding grpc_reflection to your list of dependencies in mix.exs:
{:grpc_reflection, "~> 0.2"}Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/grpc_reflection.
Reflection
This is written and tested using grpcurl and postman. It supports both v1alpha and v1 reflection by using one or both of the provided servers: rpcReflection.V1.Server or rpcReflection.V1alpha.Server
Enable reflection on your application
Ensure your protos are available using one of these options:
Recommended: expose descriptors from your proto files using the protoc elixir-out option
gen_descriptors=true, rebuild your protos with this option and note if it is present in your<module>.pb.exfileExperimental: GrpcReflection will synthesize reflection data by introspecting your service and messages — no recompile or option needed.
Create a reflection server
defmodule Helloworld.Reflection.Server do use GrpcReflection.Server, version: :v1, services: [Helloworld.Greeter.Service] endConfig Option Description versionEither :v1or:v1alpha, depending on intended client support.servicesThis is a list of GRPC services that should be included for reflection. Note
Multiple services are combined into a single reflection state. If fully-qualified symbol names collide across services, the Builder will raise at startup.
Add the reflection supervisor to your supervision tree to host the cached reflection state
children = [ ...other children, GrpcReflection ]Add your servers to your grpc endpoint
run(Helloworld.Reflection.Server)
Reflection calls can now be made on your existing endpoint, on its existing configured port
Interacting with your reflection server
List services that can be reflected:
$ grpcurl -v -plaintext 127.0.0.1:50051 list
helloworld.Greeter
List calls that are exposed by a service:
$ grpcurl -v -plaintext 127.0.0.1:50051 list helloworld.Greeter
helloworld.Greeter.SayHello
Get information about a call on a service
$ grpcurl -v -plaintext 127.0.0.1:50051 describe helloworld.Greeter.SayHello
helloworld.Greeter.SayHello is a method:
rpc SayHello ( .helloworld.HelloRequest ) returns ( .helloworld.HelloReply );
Get information about a named type used in a call on a servce:
$ grpcurl -v -plaintext 127.0.0.1:50051 describe .helloworld.HelloReply
helloworld.HelloReply is a message:
message HelloReply {
optional string message = 1;
optional .google.protobuf.Timestamp today = 2;
}
Execute a call using grpcurl that leverages reflection to fill in the gaps and generate an encoded request, and decoding the response.
$ grpcurl -plaintext -format text -d 'name: "faker"' localhost:50051 helloworld.Greeter.SayHello
message: "Hello faker"
today: <
seconds:1708412184 nanos:671267628
>
Protobuf Version Support
This module is more thoroughly tested with proto3, but it has some testing with proto2. In either case feedback is appreciated as we approach full proto support in this module.
Application Support
This is not an exhaustive list, contributions are appreciated.
| Application | Reflection version required |
|---|---|
| grpcurl | V1 |
| grpcui | V1 |
| postman | V1alpha |