Merge 378eca9891 into 4054d1d115
This commit is contained in:
commit
26baa16a7f
12
README.md
12
README.md
|
|
@ -127,10 +127,10 @@ source or protoset files.
|
|||
grpcurl localhost:8787 list
|
||||
|
||||
# Using compiled protoset files
|
||||
grpcurl -protoset my-protos.bin list
|
||||
grpcurl --protoset my-protos.bin list
|
||||
|
||||
# Using proto sources
|
||||
grpcurl -import-path ../protos -proto my-stuff.proto list
|
||||
grpcurl --import-path ../protos --proto my-stuff.proto list
|
||||
```
|
||||
|
||||
The "list" verb also lets you see all methods in a particular service:
|
||||
|
|
@ -149,10 +149,10 @@ original source that defined the element, but it will be equivalent.
|
|||
grpcurl localhost:8787 describe my.custom.server.Service.MethodOne
|
||||
|
||||
# Using compiled protoset files
|
||||
grpcurl -protoset my-protos.bin describe my.custom.server.Service.MethodOne
|
||||
grpcurl --protoset my-protos.bin describe my.custom.server.Service.MethodOne
|
||||
|
||||
# Using proto sources
|
||||
grpcurl -import-path ../protos -proto my-stuff.proto describe my.custom.server.Service.MethodOne
|
||||
grpcurl --import-path ../protos --proto my-stuff.proto describe my.custom.server.Service.MethodOne
|
||||
```
|
||||
|
||||
## Descriptor Sources
|
||||
|
|
@ -176,8 +176,8 @@ and ask it for its descriptors.
|
|||
To use `grpcurl` on servers that do not support reflection, you can use `.proto` source
|
||||
files.
|
||||
|
||||
In addition to using `-proto` flags to point `grpcurl` at the relevant proto source file(s),
|
||||
you may also need to supply `-import-path` flags to tell `grpcurl` the folders from which
|
||||
In addition to using `--proto` flags to point `grpcurl` at the relevant proto source file(s),
|
||||
you may also need to supply `--import-path` flags to tell `grpcurl` the folders from which
|
||||
dependencies can be imported.
|
||||
|
||||
Just like when compiling with `protoc`, you do *not* need to provide an import path for the
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
|
@ -12,6 +11,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
|
||||
"github.com/fullstorydev/grpcurl"
|
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
|
|
@ -34,24 +35,24 @@ var (
|
|||
|
||||
flags = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
|
||||
|
||||
help = flags.Bool("help", false, prettify(`
|
||||
help = flags.BoolP("help", "h", false, prettify(`
|
||||
Print usage instructions and exit.`))
|
||||
printVersion = flags.Bool("version", false, prettify(`
|
||||
Print version.`))
|
||||
plaintext = flags.Bool("plaintext", false, prettify(`
|
||||
Use plain-text HTTP/2 when connecting to server (no TLS).`))
|
||||
insecure = flags.Bool("insecure", false, prettify(`
|
||||
insecure = flags.BoolP("insecure", "k", false, prettify(`
|
||||
Skip server certificate and domain verification. (NOT SECURE!) Not
|
||||
valid with -plaintext option.`))
|
||||
valid with --plaintext option.`))
|
||||
cacert = flags.String("cacert", "", prettify(`
|
||||
File containing trusted root certificates for verifying the server.
|
||||
Ignored if -insecure is specified.`))
|
||||
cert = flags.String("cert", "", prettify(`
|
||||
Ignored if --insecure is specified.`))
|
||||
cert = flags.StringP("cert", "E", "", prettify(`
|
||||
File containing client certificate (public key), to present to the
|
||||
server. Not valid with -plaintext option. Must also provide -key option.`))
|
||||
server. Not valid with --plaintext option. Must also provide --key option.`))
|
||||
key = flags.String("key", "", prettify(`
|
||||
File containing client private key, to present to the server. Not valid
|
||||
with -plaintext option. Must also provide -cert option.`))
|
||||
with --plaintext option. Must also provide --cert option.`))
|
||||
protoset multiString
|
||||
protoFiles multiString
|
||||
importPaths multiString
|
||||
|
|
@ -61,11 +62,11 @@ var (
|
|||
authority = flags.String("authority", "", prettify(`
|
||||
Value of :authority pseudo-header to be use with underlying HTTP/2
|
||||
requests. It defaults to the given address.`))
|
||||
data = flags.String("d", "", prettify(`
|
||||
data = flags.StringP("data", "d", "", prettify(`
|
||||
Data for request contents. If the value is '@' then the request contents
|
||||
are read from stdin. For calls that accept a stream of requests, the
|
||||
contents should include all such request messages concatenated together
|
||||
(possibly delimited; see -format).`))
|
||||
(possibly delimited; see --format).`))
|
||||
format = flags.String("format", "json", prettify(`
|
||||
The format of request data. The allowed values are 'json' or 'text'. For
|
||||
'json', the input data must be in JSON format. Multiple request values
|
||||
|
|
@ -95,14 +96,14 @@ var (
|
|||
Emit default values for JSON-encoded responses.`))
|
||||
msgTemplate = flags.Bool("msg-template", false, prettify(`
|
||||
When describing messages, show a template of input data.`))
|
||||
verbose = flags.Bool("v", false, prettify(`
|
||||
verbose = flags.BoolP("verbose", "v", false, prettify(`
|
||||
Enable verbose output.`))
|
||||
serverName = flags.String("servername", "", prettify(`
|
||||
Override server name when validating TLS certificate.`))
|
||||
)
|
||||
|
||||
func init() {
|
||||
flags.Var(&addlHeaders, "H", prettify(`
|
||||
flags.VarP(&addlHeaders, "headers", "H", prettify(`
|
||||
Additional headers in 'name: value' format. May specify more than one
|
||||
via multiple flags. These headers will also be included in reflection
|
||||
requests requests to a server.`))
|
||||
|
|
@ -122,8 +123,8 @@ func init() {
|
|||
'list' action lists the services found in the given descriptors (vs.
|
||||
those exposed by the remote server), and the 'describe' action describes
|
||||
symbols found in the given descriptors. May specify more than one via
|
||||
multiple -protoset flags. It is an error to use both -protoset and
|
||||
-proto flags.`))
|
||||
multiple --protoset flags. It is an error to use both --protoset and
|
||||
--proto flags.`))
|
||||
flags.Var(&protoFiles, "proto", prettify(`
|
||||
The name of a proto source file. Source files given will be used to
|
||||
determine the RPC schema instead of querying for it from the remote
|
||||
|
|
@ -131,15 +132,15 @@ func init() {
|
|||
the services found in the given files and their imports (vs. those
|
||||
exposed by the remote server), and the 'describe' action describes
|
||||
symbols found in the given files. May specify more than one via multiple
|
||||
-proto flags. Imports will be resolved using the given -import-path
|
||||
--proto flags. Imports will be resolved using the given --import-path
|
||||
flags. Multiple proto files can be specified by specifying multiple
|
||||
-proto flags. It is an error to use both -protoset and -proto flags.`))
|
||||
--proto flags. It is an error to use both --protoset and --proto flags.`))
|
||||
flags.Var(&importPaths, "import-path", prettify(`
|
||||
The path to a directory from which proto sources can be imported, for
|
||||
use with -proto flags. Multiple import paths can be configured by
|
||||
specifying multiple -import-path flags. Paths will be searched in the
|
||||
use with --proto flags. Multiple import paths can be configured by
|
||||
specifying multiple --import-path flags. Paths will be searched in the
|
||||
order given. If no import paths are given, all files (including all
|
||||
imports) must be provided as -proto flags, and grpcurl will attempt to
|
||||
imports) must be provided as --proto flags, and grpcurl will attempt to
|
||||
resolve all import statements from the set of file names given.`))
|
||||
}
|
||||
|
||||
|
|
@ -154,6 +155,10 @@ func (s *multiString) Set(value string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *multiString) Type() string {
|
||||
return "stringSlice"
|
||||
}
|
||||
|
||||
func main() {
|
||||
flags.Usage = usage
|
||||
flags.Parse(os.Args[1:])
|
||||
|
|
@ -168,34 +173,34 @@ func main() {
|
|||
|
||||
// Do extra validation on arguments and figure out what user asked us to do.
|
||||
if *connectTimeout < 0 {
|
||||
fail(nil, "The -connect-timeout argument must not be negative.")
|
||||
fail(nil, "The --connect-timeout argument must not be negative.")
|
||||
}
|
||||
if *keepaliveTime < 0 {
|
||||
fail(nil, "The -keepalive-time argument must not be negative.")
|
||||
fail(nil, "The --keepalive-time argument must not be negative.")
|
||||
}
|
||||
if *maxTime < 0 {
|
||||
fail(nil, "The -max-time argument must not be negative.")
|
||||
fail(nil, "The --max-time argument must not be negative.")
|
||||
}
|
||||
if *maxMsgSz < 0 {
|
||||
fail(nil, "The -max-msg-sz argument must not be negative.")
|
||||
fail(nil, "The --max-msg-sz argument must not be negative.")
|
||||
}
|
||||
if *plaintext && *insecure {
|
||||
fail(nil, "The -plaintext and -insecure arguments are mutually exclusive.")
|
||||
fail(nil, "The --plaintext and --insecure arguments are mutually exclusive.")
|
||||
}
|
||||
if *plaintext && *cert != "" {
|
||||
fail(nil, "The -plaintext and -cert arguments are mutually exclusive.")
|
||||
fail(nil, "The --plaintext and --cert arguments are mutually exclusive.")
|
||||
}
|
||||
if *plaintext && *key != "" {
|
||||
fail(nil, "The -plaintext and -key arguments are mutually exclusive.")
|
||||
fail(nil, "The --plaintext and --key arguments are mutually exclusive.")
|
||||
}
|
||||
if (*key == "") != (*cert == "") {
|
||||
fail(nil, "The -cert and -key arguments must be used together and both be present.")
|
||||
fail(nil, "The --cert and --key arguments must be used together and both be present.")
|
||||
}
|
||||
if *format != "json" && *format != "text" {
|
||||
fail(nil, "The -format option must be 'json' or 'text.")
|
||||
fail(nil, "The --format option must be 'json' or 'text.")
|
||||
}
|
||||
if *emitDefaults && *format != "json" {
|
||||
warn("The -emit-defaults is only used when using json format.")
|
||||
warn("The --emit-defaults is only used when using json format.")
|
||||
}
|
||||
|
||||
args := flags.Args()
|
||||
|
|
@ -232,10 +237,10 @@ func main() {
|
|||
args = args[1:]
|
||||
} else {
|
||||
if *data != "" {
|
||||
warn("The -d argument is not used with 'list' or 'describe' verb.")
|
||||
warn("The --data argument is not used with 'list' or 'describe' verb.")
|
||||
}
|
||||
if len(rpcHeaders) > 0 {
|
||||
warn("The -rpc-header argument is not used with 'list' or 'describe' verb.")
|
||||
warn("The --rpc-header argument is not used with 'list' or 'describe' verb.")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
symbol = args[0]
|
||||
|
|
@ -253,13 +258,13 @@ func main() {
|
|||
fail(nil, "No host:port specified, no protoset specified, and no proto sources specified.")
|
||||
}
|
||||
if len(protoset) > 0 && len(reflHeaders) > 0 {
|
||||
warn("The -reflect-header argument is not used when -protoset files are used.")
|
||||
warn("The --reflect-header argument is not used when --protoset files are used.")
|
||||
}
|
||||
if len(protoset) > 0 && len(protoFiles) > 0 {
|
||||
fail(nil, "Use either -protoset files or -proto files, but not both.")
|
||||
fail(nil, "Use either --protoset files or --proto files, but not both.")
|
||||
}
|
||||
if len(importPaths) > 0 && len(protoFiles) == 0 {
|
||||
warn("The -import-path argument is not used unless -proto files are used.")
|
||||
warn("The --import-path argument is not used unless --proto files are used.")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
|
@ -549,7 +554,7 @@ method's request type will be sent.
|
|||
The address will typically be in the form "host:port" where host can be an IP
|
||||
address or a hostname and port is a numeric port or service name. If an IPv6
|
||||
address is given, it must be surrounded by brackets, like "[2001:db8::1]". For
|
||||
Unix variants, if a -unix=true flag is present, then the address must be the
|
||||
Unix variants, if a --unix=true flag is present, then the address must be the
|
||||
path to the domain socket.
|
||||
|
||||
Available flags:
|
||||
|
|
@ -591,7 +596,7 @@ func fail(err error, msg string, args ...interface{}) {
|
|||
exit(1)
|
||||
} else {
|
||||
// nil error means it was CLI usage issue
|
||||
fmt.Fprintf(os.Stderr, "Try '%s -help' for more details.\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stderr, "Try '%s --help' for more details.\n", os.Args[0])
|
||||
exit(2)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -3,6 +3,7 @@ module github.com/fullstorydev/grpcurl
|
|||
require (
|
||||
github.com/golang/protobuf v1.3.1
|
||||
github.com/jhump/protoreflect v1.5.0
|
||||
github.com/spf13/pflag v1.0.3
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
||||
google.golang.org/grpc v1.21.0
|
||||
)
|
||||
|
|
|
|||
5
go.sum
5
go.sum
|
|
@ -7,8 +7,12 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
|||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/jhump/protoreflect v1.4.4 h1:kySdALZUh7xRtW6UoZjjHtlR8k7rLzx5EXJFRvsO5UY=
|
||||
github.com/jhump/protoreflect v1.4.4/go.mod h1:gZ3i/BeD62fjlaIL0VW4UDMT70CTX+3m4pOnAlJ0BX8=
|
||||
github.com/jhump/protoreflect v1.5.0 h1:NgpVT+dX71c8hZnxHof2M7QDK7QtohIJ7DYycjnkyfc=
|
||||
github.com/jhump/protoreflect v1.5.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -16,6 +20,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJV
|
|||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
|||
Loading…
Reference in New Issue