This commit is contained in:
irsl 2026-02-20 07:30:12 -08:00 committed by GitHub
commit 22e9a5a991
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 91 additions and 32 deletions

View File

@ -174,6 +174,13 @@ var (
permitted if they are both set to the same value, to increase backwards
compatibility with earlier releases that allowed both to be set).`))
reflection = optionalBoolFlag{val: true}
convertMessage = flags.String("convert-message", "", prettify(`
Turns the tool into an offline converter; the proto representation of
the JSON input will be printed to the standard output.
This parameter should specify the fully qualified name of the protobuf
message definition (e.g. some.service/ReadRequest).
`))
)
func init() {
@ -369,28 +376,35 @@ func main() {
}
args := flags.Args()
convertJson := *convertMessage != ""
if len(args) == 0 {
fail(nil, "Too few arguments.")
}
var target string
if args[0] != "list" && args[0] != "describe" {
target = args[0]
args = args[1:]
}
if len(args) == 0 {
fail(nil, "Too few arguments.")
}
var list, describe, invoke bool
if args[0] == "list" {
list = true
args = args[1:]
} else if args[0] == "describe" {
describe = true
args = args[1:]
if len(args) != 0 {
if convertJson {
fail(nil, "Target service should be omitted for offline conversions.")
}
if args[0] != "list" && args[0] != "describe" {
target = args[0]
args = args[1:]
}
if args[0] == "list" {
list = true
args = args[1:]
} else if args[0] == "describe" {
describe = true
args = args[1:]
} else {
invoke = true
}
} else {
invoke = true
if !convertJson {
fail(nil, "Too few arguments.")
}
}
verbosityLevel := 0
@ -417,7 +431,7 @@ func main() {
symbol = args[0]
args = args[1:]
} else {
if *data != "" {
if *data != "" && !convertJson {
warn("The -d argument is not used with 'list' or 'describe' verb.")
}
if len(rpcHeaders) > 0 {
@ -785,9 +799,10 @@ func main() {
} else {
// Invoke an RPC
if cc == nil {
if cc == nil && !convertJson {
cc = dial()
}
var in io.Reader
if *data == "@" {
in = os.Stdin
@ -808,6 +823,16 @@ func main() {
if err != nil {
fail(err, "Failed to construct request parser and formatter for %q", *format)
}
if convertJson {
proto, err:= grpcurl.ConvertMessage(descSource, *convertMessage, rf.Next)
if err != nil {
fail(err, "Error converting message %q", *convertMessage)
}
os.Stdout.Write(proto)
os.Exit(0)
}
h := &grpcurl.DefaultEventHandler{
Out: os.Stdout,
Formatter: formatter,

View File

@ -119,18 +119,7 @@ func InvokeRPC(ctx context.Context, source DescriptorSource, ch grpcdynamic.Chan
handler.OnResolveMethod(mtd)
// we also download any applicable extensions so we can provide full support for parsing user-provided data
var ext dynamic.ExtensionRegistry
alreadyFetched := map[string]bool{}
if err = fetchAllExtensions(source, &ext, mtd.GetInputType(), alreadyFetched); err != nil {
return fmt.Errorf("error resolving server extensions for message %s: %v", mtd.GetInputType().GetFullyQualifiedName(), err)
}
if err = fetchAllExtensions(source, &ext, mtd.GetOutputType(), alreadyFetched); err != nil {
return fmt.Errorf("error resolving server extensions for message %s: %v", mtd.GetOutputType().GetFullyQualifiedName(), err)
}
msgFactory := dynamic.NewMessageFactoryWithExtensionRegistry(&ext)
req := msgFactory.NewMessage(mtd.GetInputType())
req, msgFactory, err:= getExtensions(source, mtd.GetInputType())
handler.OnSendHeaders(md)
ctx = metadata.NewOutgoingContext(ctx, md)
@ -407,3 +396,48 @@ func parseSymbol(svcAndMethod string) (string, string) {
}
return svcAndMethod[:pos], svcAndMethod[pos+1:]
}
func ConvertMessage(source DescriptorSource, messageFullName string, requestData RequestSupplier) ([]byte, error) {
dsc, err := source.FindSymbol(messageFullName)
if err != nil {
return nil, err
}
md, ok := dsc.(*desc.MessageDescriptor)
if ! ok {
return nil, fmt.Errorf("%q should point to a message descriptor instead of %d:", messageFullName, md)
}
req, _, err:= getExtensions(source, md)
if err != nil {
return nil, err
}
err = requestData(req)
if err != nil {
return nil, err
}
re, err:= proto.Marshal(req)
if err != nil {
return nil, err
}
return re, nil
}
func getExtensions(source DescriptorSource, md *desc.MessageDescriptor) (req proto.Message, msgFactory *dynamic.MessageFactory, err error) {
// we also download any applicable extensions so we can provide full support for parsing user-provided data
var ext dynamic.ExtensionRegistry
alreadyFetched := map[string]bool{}
if err = fetchAllExtensions(source, &ext, md, alreadyFetched); err != nil {
return nil, nil, fmt.Errorf("error resolving server extensions for message %s: %v", md.GetFullyQualifiedName(), err)
}
if err = fetchAllExtensions(source, &ext, md, alreadyFetched); err != nil {
return nil, nil, fmt.Errorf("error resolving server extensions for message %s: %v", md.GetFullyQualifiedName(), err)
}
msgFactory = dynamic.NewMessageFactoryWithExtensionRegistry(&ext)
req = msgFactory.NewMessage(md)
return req, msgFactory, nil
}