diff --git a/README.md b/README.md index df82c12..4f4a8c9 100644 --- a/README.md +++ b/README.md @@ -47,14 +47,15 @@ This is written and tested using [grpcurl](https://github.com/fullstorydev/grpcu end ``` or both as desired. `version` is the grpc reflection spec, which can be `v1` or `v1alpha`. `services` is the services that will be exposed by that server by reflection. You can expose a service through both services if desired. -1. Add the reflection supervisor to your supervision tree to host the cached reflection state + Instead of using an explicit list of services, you may alternatively use `{:all, MyApp.GrpcEndpoint}`, to include all services from an endpoint. This is a more succint alternative if you want to expose reflection for all services in your endpoint. On the other hand, you lose the fine-grained control of the ehaustive list. +3. Add the reflection supervisor to your supervision tree to host the cached reflection state ```elixir children = [ ...other children, GrpcReflection ] ``` -1. Add your servers to your grpc endpoint +4. Add your servers to your grpc endpoint ## interacting with your reflection server @@ -82,7 +83,7 @@ message HelloReply { $ grpcurl -plaintext -format text -d 'name: "faker"' localhost:50051 helloworld.Greeter.SayHello message: "Hello faker" today: < - seconds:1708412184 nanos:671267628 + seconds:1708412184 nanos:671267628 > ``` diff --git a/lib/grpc_reflection.ex b/lib/grpc_reflection.ex index dd3b345..1179d7a 100644 --- a/lib/grpc_reflection.ex +++ b/lib/grpc_reflection.ex @@ -11,15 +11,15 @@ defmodule GrpcReflection do defmodule Helloworld.Reflection.Server do use GrpcReflection.Server, version: :v1, - services: [Helloworld.Greeter.Service] + services: [Helloworld.Greeter.Service] # alternatively, `{:all, HelloWorld.Endpoint}` can be used to include all services from the endpoint. end ``` 2. Add the reflection supervisor to your supervision tree ```elixir children = [ + GrpcReflection, {GRPC.Server.Supervisor, endpoint: Helloworld.Endpoint, port: 50051, start_server: true}, - GrpcReflection ] ``` diff --git a/lib/grpc_reflection/service/agent.ex b/lib/grpc_reflection/service/agent.ex index f24f7ac..f7b4070 100644 --- a/lib/grpc_reflection/service/agent.ex +++ b/lib/grpc_reflection/service/agent.ex @@ -14,6 +14,12 @@ defmodule GrpcReflection.Service.Agent do name = Keyword.get(opts, :name) services = Keyword.get(opts, :services) + services = + case services do + {:all, endpoint} -> endpoint_services(endpoint) + list -> list + end + case Builder.build_reflection_tree(services) do {:ok, state} -> Agent.start_link(fn -> state end, name: name) @@ -24,6 +30,12 @@ defmodule GrpcReflection.Service.Agent do end end + defp endpoint_services(endpoint) do + :servers + |> endpoint.__meta__() + |> Enum.map(fn server -> server.__meta__(:service) end) + end + @spec list_services(cfg_t()) :: list(binary) def list_services(cfg) do name = start_agent_on_first_call(cfg) diff --git a/test/grpc_reflection_test.exs b/test/grpc_reflection_test.exs index 5ad0772..a96079a 100644 --- a/test/grpc_reflection_test.exs +++ b/test/grpc_reflection_test.exs @@ -68,4 +68,19 @@ defmodule GrpcReflection.Test do Service.get_by_filename("helloworld.HelloRequest.proto") end end + + test "server reading services from endpoint" do + defmodule AutoServiceDiscoveryServer do + use GrpcReflection.Server, + version: :v1, + services: {:all, GrpcReflection.TestEndpoint.Endpoint} + end + + assert AutoServiceDiscoveryServer.list_services() == + [ + "grpc.reflection.v1alpha.ServerReflection", + "grpc.reflection.v1.ServerReflection", + "helloworld.Greeter" + ] + end end