Awesome
gcall
Simple gRPC command-line interface
Installation
$ npm install -g gcall
Usage
Usage: gcall [options] [rpc]
Options:
-h, --help output usage information
-V, --version output the version number
-p, --proto <file> Path to protocol buffer definition.
-h, --host <host> The service host.
-d, --data <data> Input data, otherwise standard input.
-o, --output <file> Output path, otherwise standard output.
-m, --metadata <data> Metadata value.
-s, --secure Use secure options.
-S, --service <name> Service name. Default is the 0th found in definition.
-j, --json [jsonpath] Input is JSON. JSONPath for parsing. Default: '*'. Set to empty to turn off JSON parsing.
-b, --breaker [characters] Separator character(s) for JSON stream response. If flag set, but no separator is defined, default newline is used as separator.
-a, --array Output response stream as an array. Default: false.
-r, --rpc <name> RPC to call.
-c, --config <file> YAML or JSON config file with all the options.
-C, --color Color output. Useful for terminal output.
-P, --pretty Pretty print output.
-R, --raw Raw output. Do not try to JSON stringify or do anything.
-E, --encoding [encoding] Encoding for raw mode file output. Default: utf8.
-X, --silent Silent. Do not output anything. Just do the call.
Features
- Works with all call types
- Takes input from standard input allowing for piping or using
-d
data CLI argument - Metadata options
- Config file option
- Various output formatting options
Examples
Basic
List all available RPC's in a service
$ gcall -p ./protos/route_guide.proto
› GetFeature (Point) returns (Feature)
› ListFeatures (Rectangle) returns (stream Feature)
› RecordRoute (stream Point) returns (RouteSummary)
› RouteChat (stream RouteNote) returns (stream RouteNote)
Request / Response
Simple request / response caller
$ gcall \
-p ./protos/route_guide.proto \
-d "{\"latitude\":409146138,\"longitude\":-746188906}" \
-h 0.0.0.0:50051 \
GetFeature
{"name":"Berkshire Valley Management Area Trail, Jefferson, NJ, USA","location":{"latitude":409146138,"longitude":-746188906}}
Output data to a file
$ gcall \
-p ./protos/route_guide.proto \
-d "{\"latitude\":409146138,\"longitude\":-746188906}" \
-h 0.0.0.0:50051 \
-o ./feature.json \
GetFeature
Input by piping
cat ./data.json | gcall \
-p ./protos/route_guide.proto \
-h 0.0.0.0:50051 \
GetFeature
Add metadata using -m
option
$ gcall \
-p ./protos/route_guide.proto \
-m "{\"Authorization\": \"Bearer 1234\"}" \
-d "{\"latitude\":409146138,\"longitude\":-746188906}" \
-h 0.0.0.0:50051 \
GetFeature
Pretty print with -P
option:
$ gcall \
-p ./protos/route_guide.proto \
-d "{\"latitude\":409146138,\"longitude\":-746188906}" \
-h 0.0.0.0:50051 \
-P \
GetFeature
{
"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA",
"location": {
"latitude": 409146138,
"longitude": -746188906
}
}
Inspect using colors with -C
option:
$ gcall \
-p ./protos/route_guide.proto \
-d "{\"latitude\":409146138,\"longitude\":-746188906}" \
-h 0.0.0.0:50051 \
-C \
GetFeature
{ name: 'Berkshire Valley Management Area Trail, Jefferson, NJ, USA',
location: { latitude: 409146138, longitude: -746188906 } }
Request stream
-j
flag can be used to specify JSONPath
for JSON parsing. Default is '*'
and normally it wouldn't be needed, depending on the
input data structure.
Input redirection can be used for input as well.
$ gcall.js \
-p ./protos/route_guide.proto \
-h 0.0.0.0:50051 \
-j *.location \
RecordRoute < ./feature_guide_db.json
{"point_count":100,"feature_count":64,"distance":7494392,"elapsed_time":0}
We can pipe
curl -s https://raw.githubusercontent.com/bojand/gcall/master/test/data/feature_guide_db.json | gcall.js \
-p ./protos/route_guide.proto \
-h 0.0.0.0:50051 \
-j *.location \
-P \
RecordRoute
{
"point_count": 100,
"feature_count": 64,
"distance": 7494392,
"elapsed_time": 4
}
Response stream
$ gcall.js \
-p ./protos/route_guide.proto \
-d "{\"lo\":{\"latitude\":400000000,\"longitude\":-750000000},\"hi\":{\"latitude\":405000000,\"longitude\":-742000000}}" \
-h 0.0.0.0:50051 \
ListFeatures
{"name":"3 Drake Lane, Pennington, NJ 08534, USA","location":{"latitude":402948455,"longitude":-747903913}},{"name":"330 Evelyn Avenue, Hamilton Township, NJ 08619, USA","location":{"latitude":402647019,"longitude":-747071791}},{"name":"1300 Airport Road, North Brunswick Township, NJ 08902, USA","location":{"latitude":404663628,"longitude":-744820157}},{"name":"1007 Jersey Avenue, New Brunswick, NJ 08901, USA","location":{"latitude":404701380,"longitude":-744781745}},{"name":"517-521 Huntington Drive, Manchester Township, NJ 08759, USA","location":{"latitude":400106455,"longitude":-742870190}},{"name":"1-17 Bergen Court, New Brunswick, NJ 08901, USA","location":{"latitude":404839914,"longitude":-744759616}}
We can pretty print as an array using -a
and -P
options:
$ gcall.js \
-p ./protos/route_guide.proto \
-d "{\"lo\":{\"latitude\":400000000,\"longitude\":-750000000},\"hi\":{\"latitude\":405000000,\"longitude\":-742000000}}" \
-h 0.0.0.0:50051 \
-a \
-P \
ListFeatures
[
{
"name": "3 Drake Lane, Pennington, NJ 08534, USA",
"location": {
"latitude": 402948455,
"longitude": -747903913
}
},
{
"name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA",
"location": {
"latitude": 402647019,
"longitude": -747071791
}
},
{
"name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA",
"location": {
"latitude": 404663628,
"longitude": -744820157
}
},
{
"name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA",
"location": {
"latitude": 404701380,
"longitude": -744781745
}
},
{
"name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA",
"location": {
"latitude": 400106455,
"longitude": -742870190
}
},
{
"name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA",
"location": {
"latitude": 404839914,
"longitude": -744759616
}
}
]
Or we can do a custom separator using -b
. If separator is not provided, newline
is used by default
$ gcall.js \
-p ./protos/route_guide.proto \
-d "{\"lo\":{\"latitude\":400000000,\"longitude\":-750000000},\"hi\":{\"latitude\":405000000,\"longitude\":-742000000}}" \
-b \
-h 0.0.0.0:50051 \
ListFeatures
{"name":"3 Drake Lane, Pennington, NJ 08534, USA","location":{"latitude":402948455,"longitude":-747903913}}
{"name":"330 Evelyn Avenue, Hamilton Township, NJ 08619, USA","location":{"latitude":402647019,"longitude":-747071791}}
{"name":"1300 Airport Road, North Brunswick Township, NJ 08902, USA","location":{"latitude":404663628,"longitude":-744820157}}
{"name":"1007 Jersey Avenue, New Brunswick, NJ 08901, USA","location":{"latitude":404701380,"longitude":-744781745}}
{"name":"517-521 Huntington Drive, Manchester Township, NJ 08759, USA","location":{"latitude":400106455,"longitude":-742870190}}
{"name":"1-17 Bergen Court, New Brunswick, NJ 08901, USA","location":{"latitude":404839914,"longitude":-744759616}}
Or with combination of -b
and -a
$ gcall.js \
-p ./protos/route_guide.proto \
-d "{\"lo\":{\"latitude\":400000000,\"longitude\":-750000000},\"hi\":{\"latitude\":405000000,\"longitude\":-742000000}}" \
-b \
-a \
-h 0.0.0.0:50051 \
ListFeatures
{"name":"3 Drake Lane, Pennington, NJ 08534, USA","location":{"latitude":402948455,"longitude":-747903913}}
,
{"name":"330 Evelyn Avenue, Hamilton Township, NJ 08619, USA","location":{"latitude":402647019,"longitude":-747071791}}
,
{"name":"1300 Airport Road, North Brunswick Township, NJ 08902, USA","location":{"latitude":404663628,"longitude":-744820157}}
,
{"name":"1007 Jersey Avenue, New Brunswick, NJ 08901, USA","location":{"latitude":404701380,"longitude":-744781745}}
,
{"name":"517-521 Huntington Drive, Manchester Township, NJ 08759, USA","location":{"latitude":400106455,"longitude":-742870190}}
,
{"name":"1-17 Bergen Court, New Brunswick, NJ 08901, USA","location":{"latitude":404839914,"longitude":-744759616}}]
Or just a custom separator
$ gcall.js \
-p ./protos/route_guide.proto \
-d "{\"lo\":{\"latitude\":400000000,\"longitude\":-750000000},\"hi\":{\"latitude\":405000000,\"longitude\":-742000000}}" \
-b " | " \
-h 0.0.0.0:50051 \
ListFeatures
{"name":"3 Drake Lane, Pennington, NJ 08534, USA","location":{"latitude":402948455,"longitude":-747903913}} | {"name":"330 Evelyn Avenue, Hamilton Township, NJ 08619, USA","location":{"latitude":402647019,"longitude":-747071791}} | {"name":"1300 Airport Road, North Brunswick Township, NJ 08902, USA","location":{"latitude":404663628,"longitude":-744820157}} | {"name":"1007 Jersey Avenue, New Brunswick, NJ 08901, USA","location":{"latitude":404701380,"longitude":-744781745}} | {"name":"517-521 Huntington Drive, Manchester Township, NJ 08759, USA","location":{"latitude":400106455,"longitude":-742870190}} | {"name":"1-17 Bergen Court, New Brunswick, NJ 08901, USA","location":{"latitude":404839914,"longitude":-744759616}}
Duplex
./gcall.js \
-p ./protos/route_guide.proto \
-h 0.0.0.0:50051 \
RouteChat < ./notes.json
{"location":{"latitude":0,"longitude":0},"message":"First message"}
./gcall.js \
-p ./protos/route_guide.proto \
-h 0.0.0.0:50051 \
-a \
-P \
RouteChat < ./notes.json
[
{
"location": {
"latitude": 0,
"longitude": 0
},
"message": "First message"
},
{
"location": {
"latitude": 0,
"longitude": 0
},
"message": "Fourth message"
},
{
"location": {
"latitude": 0,
"longitude": 1
},
"message": "Second message"
},
{
"location": {
"latitude": 1,
"longitude": 0
},
"message": "Third message"
}
]
Config
We can run gcall
using a config file in either JSON or YAML format.
Note that you can combine config file and command line options.
Command line options will overwrite any existing config file options.
config.json
{
"proto": "/protos/route_guide.proto",
"data": {
"latitude": 409146138,
"longitude": -746188906
},
"host": "0.0.0.0:50051",
"pretty": true,
"rpc": "GetFeature"
}
$ gcall -c config.json
{
"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA",
"location": {
"latitude": 409146138,
"longitude": -746188906
}
}
License
Apache-2.0