Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork192
Evans: more expressive universal gRPC client
License
ktr0731/evans
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Evans has been created to use easier than other existing gRPC clients.
If you want to keep your product quality, you must use CI with gRPC testing, should not do use manual testing.
Evans will complete your other use cases just like:
- Manually gRPC API inspection
- To automate some tasks by scripting
The above use cases are corresponding to Evans's two modes, REPL mode, and CLI mode.
REPL mode is the solution for first use case.
You can use it without thinking like the package name, service name, RPC name, command usage, and so on because REPL mode has powerful completion!
CLI mode is a stateless mode just likegrpc-ecosystem/polyglot.
It sends one request per one command as its name suggests.
So it is based on UNIX philosophy.
For example, read inputs fromstdin
, the command will be a filter command.
On the other hand, the command result will be outputted tostdout
by JSON formatted.
So, you can format it by any commands likejq
. Also, if you want to use the same command (e.g. use same JSON inputs), you can use--file
(-f
) option.
- Installation
- Usage (REPL)
- Usage (CLI)
- Other features
- Supported IDL (interface definition language)
- Supported Codec
- Supported Compressor
- See Also
Highly recommended methods are GitHub Releases or Homebrew because these can be updated automatically by the built-in feature in Evans.
Please seeGitHub Releases.
Available binaries are:
- macOS
- Linux
- Windows
brew tap ktr0731/evansbrew install evans
You can use our docker image to run Evans - please seecontainer registry.For example, if you want to connect to the server on hostexample.com
on port50051
using proto file in./proto/files/file-name.proto
(default working directory is/mount
):
$ docker run --rm -v"$(pwd):/mount:ro" \ ghcr.io/ktr0731/evans:latest \ --path ./proto/files \ --proto file-name.proto \ --host example.com \ --port 50051 \ repl
Go v1.20 or later is required.
go install github.com/ktr0731/evans@latest
Evans consists of some commands in REPL mode.
The proto file which read in the demonstration and its implementation are available atktr0731/grpc-test.grpc-test
's details can seegrpc-test --help
.
Enter to REPL.
cd grpc-testevans --proto api/api.proto repl
If your server is enablinggRPC reflection, you can launch Evans with only-r
(--reflection
) option.
evans -r repl
Also if the server requires secure TLS connections, you can launch Evans with the-t
(--tls
) option.
evans --tls --host example.com -r repl
To show package names of proto files REPL read:
> show package+---------+| PACKAGE |+---------+| api |+---------+
To show the summary of services or messages:
> package api> show service+---------+----------------------+-----------------------------+----------------+| SERVICE | RPC | REQUESTTYPE | RESPONSETYPE |+---------+----------------------+-----------------------------+----------------+| Example | Unary | SimpleRequest | SimpleResponse || | UnaryMessage | UnaryMessageRequest | SimpleResponse || | UnaryRepeated | UnaryRepeatedRequest | SimpleResponse || | UnaryRepeatedMessage | UnaryRepeatedMessageRequest | SimpleResponse || | UnaryRepeatedEnum | UnaryRepeatedEnumRequest | SimpleResponse || | UnarySelf | UnarySelfRequest | SimpleResponse || | UnaryMap | UnaryMapRequest | SimpleResponse || | UnaryMapMessage | UnaryMapMessageRequest | SimpleResponse || | UnaryOneof | UnaryOneofRequest | SimpleResponse || | UnaryEnum | UnaryEnumRequest | SimpleResponse || | UnaryBytes | UnaryBytesRequest | SimpleResponse || | ClientStreaming | SimpleRequest | SimpleResponse || | ServerStreaming | SimpleRequest | SimpleResponse || | BidiStreaming | SimpleRequest | SimpleResponse |+---------+----------------------+-----------------------------+----------------+> show message+-----------------------------+| MESSAGE |+-----------------------------+| SimpleRequest || SimpleResponse || Name || UnaryMessageRequest || UnaryRepeatedRequest || UnaryRepeatedMessageRequest || UnaryRepeatedEnumRequest || UnarySelfRequest || Person || UnaryMapRequest || UnaryMapMessageRequest || UnaryOneofRequest || UnaryEnumRequest || UnaryBytesRequest |+-----------------------------+
To show more description of a message:
> desc SimpleRequest+-------+-------------+| FIELD | TYPE |+-------+-------------+| name | TYPE_STRING |+-------+-------------+
Set headers for each request:
> header foo=bar
To show headers:
> show header+-------------+-------+| KEY | VAL |+-------------+-------+| foo | bar || grpc-client | evans |+-------------+-------+
Note that if you want to set comma-included string to a header value, it is required to specify--raw
option.
To remove the added header:
> header foo> show header+-------------+-------+| KEY | VAL |+-------------+-------+| grpc-client | evans |+-------------+-------+
Call a RPC:
> service Example> call Unaryname (TYPE_STRING) => ktr{ "message": "hello, ktr"}
Evans constructs a gRPC request interactively and sends the request to a gRPC server.
Finally, Evans prints the JSON formatted result.
repeated
is an array-like data structure.
You can input some values and finish withCTRL-D
> call UnaryRepeated<repeated> name (TYPE_STRING) => foo<repeated> name (TYPE_STRING) => bar<repeated> name (TYPE_STRING) => baz<repeated> name (TYPE_STRING) =>{ "message": "hello, foo, bar, baz"}
You can select one from the proposed selections.
WhenCTRL-C is entered, default value 0 will be used.
WhenCTRL-D is entered, inputting will be aborted.
> call UnaryEnum? UnaryEnumRequest [Use arrows to move, type to filter]> Male Female{ "message": "M"}
You can pass bytes as a base64-encoded string.
> call UnaryBytesdata (TYPE_BYTES) => SGVsbG8gV29ybGQh{ "message": "received: (bytes) 48 65 6c 6c 6f 20 57 6f 72 6c 64 21, (string) Hello World!"}
While evans currenty still attempts to fall back to that encoding if decodingas base64 fails, it's discouraged, and might be dropped.
Please either encode bytes as base64, or pass--bytes-as-quoted-literals
explicitly:
> call UnaryBytes --bytes-as-quoted-literalsdata (TYPE_BYTES) => \x46\x6f\x6f{ "message": "received: (bytes) 46 6f 6f, (string) Foo"}> call UnaryBytes --bytes-as-quoted-literalsdata (TYPE_BYTES) => \u65e5\u672c\u8a9e{ "message": "received: (bytes) e6 97 a5 e6 9c ac e8 aa 9e, (string) 日本語"}
You can also add the flag--bytes-as-base64
to explicitly disable thefallback behaviour.
Or add the flag--bytes-from-file
to read bytes from the provided relative path
> call UnaryBytes --bytes-from-filedata (TYPE_BYTES) => ../relative/path/to/file
Client streaming RPC accepts some requests and then returns only one response.
Finish request inputting withCTRL-D
> call ClientStreamingname (TYPE_STRING) => ktrname (TYPE_STRING) => ktrname (TYPE_STRING) => ktrname (TYPE_STRING) =>{ "message": "ktr, you greet 3 times."}
Server streaming RPC accepts only one request and then returns some responses.Each response is represented as another JSON formatted output.
name (TYPE_STRING) => ktr{ "message": "hello ktr, I greet 0 times."}{ "message": "hello ktr, I greet 1 times."}
Bidirectional streaming RPC accepts some requests and returns some responses corresponding to each request.Finish request inputting withCTRL-D
> call BidiStreamingname (TYPE_STRING) => foo{ "message": "hello foo, I greet 0 times."}{ "message": "hello foo, I greet 1 times."}{ "message": "hello foo, I greet 2 times."}name (TYPE_STRING) => bar{ "message": "hello bar, I greet 0 times."}name (TYPE_STRING) =>
Evans recognizesCTRL-C as a special key that skips the rest of the fields in the current message type.For example, we assume that we are inputtingRequest
described in the following message:
messageFullName {stringfirst_name=1;stringlast_name=2;}messageRequest {stringnickname=1;FullNamefull_name=2;}
If we enterCTRL-C at the following moment,full_name
field will be skipped.
nickname (TYPE_STRING) =>
The actual request value is just like this.
{}
If we enterCTRL-C at the following moment,last_name
field will be skipped.
nickname (TYPE_STRING) => myamorifull_name::first_name (TYPE_STRING) => aoifull_name::last_name (TYPE_STRING) =>
The actual request value is just like this.
{"nickname":"myamori","fullName": {"firstName":"aoi" }}
By default, Evans digs down each message field automatically.
For example, we assume that we are inputtingRequest
described in the following message:
messageFullName {stringfirst_name=1;stringlast_name=2;}messageRequest {FullNamefull_name=1;}
In this case, REPL promptsfull_name.first_name
automatically. To skipfull_name
itself, we can use--dig-manually
option.It asks whether dig down a message field when the prompt encountered it.
To display more enriched response, you can use--enrich
option.
> call --enrich Unaryname (TYPE_STRING) => ktrcontent-type: application/grpcheader_key1: header_val1header_key2: header_val2{ "message": "hello, ktr"}trailer_key1: trailer_val1trailer_key2: trailer_val2code: OKnumber: 0message: ""
With--repeat
option, you can repeat the previous call with the same input.
Note that Client/Bidirectional streaming RPC is not supported.
> call Unaryname (TYPE_STRING) => ktr{ "message": "hello, ktr"}> call --repeat Unaryname (TYPE_STRING) => ktr{ "message": "hello, ktr"}
CLI mode also has some commands.
list
command provides gRPC service inspection against to the gRPC server.
$ evans -r cli listapi.Examplegrpc.reflection.v1alpha.ServerReflection
If an service name is specified, it displays methods belonging to the service.
$ evans -r cli list api.Exampleapi.Example.Unaryapi.Example.UnaryBytesapi.Example.UnaryEnum...
desc
command describes the passed symbol (service, method, message, and so on).
api.Example:service Example { rpc Unary ( .api.SimpleRequest ) returns ( .api.SimpleResponse ); rpc UnaryBytes ( .api.UnaryBytesRequest ) returns ( .api.SimpleResponse ); rpc UnaryEnum ( .api.UnaryEnumRequest ) returns ( .api.SimpleResponse ); ...}
call
command invokes a method.You can input requests fromstdin
or files.
Use--file
(-f
) to specify a file.
$ cat request.json{"name":"ktr"}$ evans --proto api/api.proto cli call --file request.json api.Example.Unary{"message":"hello, ktr"}
If gRPC reflection is enabled,--reflection
(-r
) is available instead of specifying proto files.
$ evans -r cli call --file request.json api.Example.Unary{"message":"hello, ktr"}
Usestdin
.
$echo'{ "name": "ktr" }'| evans cli call api.Example.Unary{"message":"hello, ktr"}
If.evans.toml
is exist in Git project root, you can denote default values.
[default]protoFile = ["api/api.proto"]package ="api"service ="Example"
Then, the command will be more clear.
$echo'{ "name": "ktr" }'| evans cli call Unary{"message":"hello, ktr"}
$echo'{ "name": ["foo", "bar"] }'| evans -r cli call api.Example.UnaryRepeated{"message":"hello, foo, bar"}
$echo'{ "choice": 0 }'| evans -r cli call api.Example.UnaryEnum{"message":"1"}
You need to encode bytes by Base64.
This constraint is come from Go's standard packageencoding/json
$echo'Foo'| base64Rm9vCg==$echo'{"data": "Rm9vCg=="}'| evans -r cli call api.Example.UnaryBytes
$echo'{ "name": "ktr" } { "name": "ktr" }'| evans -r cli call api.Example.ClientStreaming{"message":"ktr, you greet 2 times."}
$echo'{ "name": "ktr" }'| evans -r cli call api.Example.ServerStreaming{"message":"hello ktr, I greet 0 times."}{"message":"hello ktr, I greet 1 times."}{"message":"hello ktr, I greet 2 times."}
$echo'{ "name": "foo" } { "name": "bar" }'| evans -r cli call api.Example.BidiStreaming{"message":"hello foo, I greet 0 times."}{"message":"hello foo, I greet 1 times."}{"message":"hello foo, I greet 2 times."}{"message":"hello foo, I greet 3 times."}{"message":"hello bar, I greet 0 times."}
To display more enriched response, you can use--enrich
option.
$ echo '{"name": "ktr"}' | evans -r cli call --enrich api.Example.Unary ~/.ghq/src/github.com/ktr0731/grpc-test mastercontent-type: application/grpcheader_key1: header_val1header_key2: header_val2{ "message": "hello, ktr"}trailer_key1: trailer_val1trailer_key2: trailer_val2code: OKnumber: 0message: ""
JSON output is also available with--out json
option.
Evans also support gRPC-Web protocol.
Tested gRPC-Web implementations are:
At the moment TLS is not supported for gRPC-Web.
About
Evans: more expressive universal gRPC client
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Packages0
Uh oh!
There was an error while loading.Please reload this page.