Skip to content

Commit 38f9fd6

Browse files
authored
Clean up internal calls and Readme (#52)
* Clean up * clean up sentence * review sample readme
1 parent 14da45d commit 38f9fd6

File tree

9 files changed

+182
-203
lines changed

9 files changed

+182
-203
lines changed

README.md

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,14 @@ Server reflection allows servers to assist clients in runtime construction of re
55
According to the [GRPC Server Reflection Protocol
66
](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md), 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.
77

8-
GrpcReflection, implemented as a gRPC server using `grpc-elixir`, adds reflection support to a `grpc-elixir` based application.
8+
GrpcReflection adds reflection support to a `grpc-elixir` based application. It is a supervised application that can support implemented as a gRPC server using `grpc-elixir`, .
99

1010
## Installation
1111

1212
The package can be installed by adding `grpc_reflection` to your list of dependencies in `mix.exs`:
1313

1414
```elixir
15-
def deps do
16-
[
17-
{:grpc_reflection, "~> 0.1.0"}
18-
]
19-
end
15+
{:grpc_reflection, "~> 0.1.5"}
2016
```
2117

2218
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
@@ -25,37 +21,42 @@ be found at <https://hexdocs.pm/grpc_reflection>.
2521

2622
# Reflection
2723

28-
This is written and tested using [grpcurl](https://github.com/fullstorydev/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`
24+
This is written and tested using [grpcurl](https://github.com/fullstorydev/grpcurl) and [postman](https://www.postman.com). It supports both v1alpha and v1 reflection by using one or both of the provided servers: `rpcReflection.V1.Server` or `rpcReflection.V1alpha.Server`
2925

3026
## Enable reflection on your application
3127

32-
1. Rebuild your protos with descriptors on. Each module and/or service that you would like to expose through reflection must use the protoc elixir-out option `gen_descriptors=true`
28+
1. Rebuild your protos with descriptors enabled. Each module and/or service that you would like to expose through reflection must use the protoc elixir-out option `gen_descriptors=true`.
29+
3330
1. Create a reflection server
34-
```elixir
35-
defmodule Helloworld.Reflection.Server do
36-
use GrpcReflection.Server,
37-
version: :v1,
38-
services: [Helloworld.Greeter.Service]
39-
end
40-
```
41-
or
42-
```elixir
43-
defmodule Helloworld.Reflection.Server2 do
44-
use GrpcReflection.Server,
45-
version: :v1alpha,
46-
services: [Helloworld.Greeter.Service]
47-
end
48-
```
49-
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.
31+
32+
```elixir
33+
defmodule Helloworld.Reflection.Server do
34+
use GrpcReflection.Server,
35+
version: :v1,
36+
services: [Helloworld.Greeter.Service]
37+
end
38+
```
39+
40+
| Config Option | Description |
41+
| ------------- | ---------------------------------------------------------------------- |
42+
| version | Either `:v1` or `:v2` depending on intended client support |
43+
| services | This is a list of GRPC services that should be included for reflection |
44+
5045
1. Add the reflection supervisor to your supervision tree to host the cached reflection state
51-
```elixir
52-
children = [
53-
...other children,
54-
GrpcReflection
55-
]
56-
```
46+
47+
```elixir
48+
children = [
49+
...other children,
50+
GrpcReflection
51+
]
52+
```
53+
5754
1. Add your servers to your grpc endpoint
5855

56+
```elixir
57+
run(Helloworld.Reflection.Server)
58+
```
59+
5960
## interacting with your reflection server
6061

6162
Here are some example `grpcurl` commands and responses excersizing the reflection capabilities
@@ -82,19 +83,19 @@ message HelloReply {
8283
$ grpcurl -plaintext -format text -d 'name: "faker"' localhost:50051 helloworld.Greeter.SayHello
8384
message: "Hello faker"
8485
today: <
85-
seconds:1708412184 nanos:671267628
86+
seconds:1708412184 nanos:671267628
8687
>
8788
```
8889

8990
## Protobuf Version Support
9091

91-
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.
92+
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.
9293

9394
## Application Support
9495

9596
This is **not** an exhaustive list, contributions are appreciated.
9697

97-
| Application | Reflection version required |
98-
| ------------- | ------------- |
99-
| grpcurl | V1 |
100-
| postman | V1alpha |
98+
| Application | Reflection version required |
99+
| ----------- | --------------------------- |
100+
| grpcurl | V1 |
101+
| postman | V1alpha |

examples/helloworld/README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,40 @@
22

33
This example is mostly copied directly from `grpc-elixir`, with the exception that this example has:
44

5-
1. Compiled protos with descriptors on. This is required for the reflection service to run correctly
5+
1. Compiled protos with descriptors on. This is required for the reflection service to run correctly
66
1. Is running the `GrpcReflection.Server.V1` server in its endpoint
77
1. Configured the `GrpcReflection.Server.V1` to include `helloworld` in its services
88

99
## Usage
1010

1111
1. Install deps and compile
12+
1213
```shell
1314
$ mix do deps.get, compile
1415
```
1516

1617
2. Compile protos
18+
1719
```shell
1820
$ ./generate_protos.sh
1921
```
2022

2123
3. Run the server
24+
2225
```shell
2326
$ mix run --no-halt
2427
```
2528

2629
4. Run the client script
30+
2731
```shell
2832
$ mix run priv/client.exs
2933
```
3034

3135
5. Explore the reflection services
36+
3237
```shell
3338
$ grpcurl -v -plaintext 127.0.0.1:50051 list
34-
grpc.reflection.v1.ServerReflection
3539
helloworld.Greeter
3640

3741
$ grpcurl -v -plaintext 127.0.0.1:50051 list helloworld.Greeter
@@ -51,7 +55,7 @@ message HelloReply {
5155
$ grpcurl -plaintext -format text -d 'name: "faker"' localhost:50051 helloworld.Greeter.SayHello
5256
message: "Hello faker"
5357
today: <
54-
seconds:1708412184 nanos:671267628
58+
seconds:1708412184 nanos:671267628
5559
>
5660
```
5761

@@ -60,10 +64,13 @@ today: <
6064
1. Modify the proto `priv/protos/helloworld.proto`
6165
2. Install `protoc` [here](https://developers.google.com/protocol-buffers/docs/downloads)
6266
3. Install `protoc-gen-elixir`
67+
6368
```
6469
mix escript.install hex protobuf
6570
```
71+
6672
4. Generate the code:
73+
6774
```shell
6875
$ ./generate_protos.sh
6976
```

examples/helloworld/lib/protos/helloworld.pb.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defmodule Helloworld.HelloRequest do
33
The request message containing the user's name.
44
"""
55

6-
use Protobuf, protoc_gen_elixir_version: "0.14.0", syntax: :proto3
6+
use Protobuf, protoc_gen_elixir_version: "0.14.1", syntax: :proto3
77

88
def descriptor do
99
# credo:disable-for-next-line
@@ -45,7 +45,7 @@ defmodule Helloworld.HelloReply do
4545
The response message containing the greetings
4646
"""
4747

48-
use Protobuf, protoc_gen_elixir_version: "0.14.0", syntax: :proto3
48+
use Protobuf, protoc_gen_elixir_version: "0.14.1", syntax: :proto3
4949

5050
def descriptor do
5151
# credo:disable-for-next-line
@@ -102,7 +102,7 @@ defmodule Helloworld.Greeter.Service do
102102
The greeting service definition.
103103
"""
104104

105-
use GRPC.Service, name: "helloworld.Greeter", protoc_gen_elixir_version: "0.14.0"
105+
use GRPC.Service, name: "helloworld.Greeter", protoc_gen_elixir_version: "0.14.1"
106106

107107
def descriptor do
108108
# credo:disable-for-next-line

examples/helloworld/mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ defmodule Helloworld.Mixfile do
2121
{:grpc, "~> 0.9"},
2222
{:grpc_reflection, path: "../.."},
2323
{:protobuf, "~> 0.14"},
24-
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}
24+
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}
2525
]
2626
end
2727
end

examples/helloworld/mix.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
%{
22
"cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"},
33
"cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
4-
"dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"},
5-
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
4+
"dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
5+
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
66
"grpc": {:hex, :grpc, "0.9.0", "1b930a57272d4356ea65969b984c2eb04f3dab81420e1e28f0e6ec04b8f88515", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:cowboy, "~> 2.10", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowlib, "~> 2.12", [hex: :cowlib, repo: "hexpm", optional: false]}, {:gun, "~> 2.0", [hex: :gun, repo: "hexpm", optional: false]}, {:jason, ">= 0.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint, "~> 1.5", [hex: :mint, repo: "hexpm", optional: false]}, {:protobuf, "~> 0.11", [hex: :protobuf, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7c059698248738fcf7ad551f1d78f4a3d2e0642a72a5834f2a0b0db4b9f3d2b5"},
77
"gun": {:hex, :gun, "2.1.0", "b4e4cbbf3026d21981c447e9e7ca856766046eff693720ba43114d7f5de36e87", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "52fc7fc246bfc3b00e01aea1c2854c70a366348574ab50c57dfe796d24a0101d"},
88
"hpax": {:hex, :hpax, "1.0.2", "762df951b0c399ff67cc57c3995ec3cf46d696e41f0bba17da0518d94acd4aac", [:mix], [], "hexpm", "2f09b4c1074e0abd846747329eaa26d535be0eb3d189fa69d812bfb8bfefd32f"},
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
defmodule GrpcReflection.Server.Process do
2+
@moduledoc false
3+
require Logger
4+
5+
def reflect(state_mod, {:list_services, _}) do
6+
state_mod.list_services()
7+
|> Enum.map(fn name -> %{name: name} end)
8+
|> then(fn services ->
9+
{:ok, {:list_services_response, %{service: services}}}
10+
end)
11+
end
12+
13+
def reflect(state_mod, {:file_containing_symbol, symbol}) do
14+
with {:ok, description} <- state_mod.get_by_symbol(symbol) do
15+
{:ok, {:file_descriptor_response, description}}
16+
end
17+
end
18+
19+
def reflect(state_mod, {:file_by_filename, filename}) do
20+
with {:ok, description} <- state_mod.get_by_filename(filename) do
21+
{:ok, {:file_descriptor_response, description}}
22+
end
23+
end
24+
25+
def reflect(
26+
state_mod,
27+
{:file_containing_extension,
28+
%{containing_type: containing_type, extension_number: _extension_number}}
29+
) do
30+
with {:ok, description} <- state_mod.get_by_extension(containing_type) do
31+
{:ok, {:file_descriptor_response, description}}
32+
end
33+
end
34+
35+
def reflect(state_mod, {:all_extension_numbers_of_type, mod}) do
36+
with {:ok, extension_numbers} <- state_mod.get_extension_numbers_by_type(mod) do
37+
{:ok,
38+
{:all_extension_numbers_response,
39+
%{base_type_name: mod, extension_number: extension_numbers}}}
40+
end
41+
end
42+
43+
def reflect(_state_mod, message_request) do
44+
Logger.warning("received unexpected reflection request: #{inspect(message_request)}")
45+
{:error, :unimplemented}
46+
end
47+
end

0 commit comments

Comments
 (0)