diff --git a/cmd/grpcui/grpcui.go b/cmd/grpcui/grpcui.go index 9e4317fa..8a05799c 100644 --- a/cmd/grpcui/grpcui.go +++ b/cmd/grpcui/grpcui.go @@ -155,6 +155,9 @@ var ( suite as a sequence of RPCs. This is similar to the "collections" feature in postman. The format of this file is the same as used when saving history from the gRPC UI "History" tab.`)) + overrideGRPCCurl = flags.String("override-grpccurl-cmd", "", prettify(` + Override the command outputted in the gRPCurl section of the request tab. + `)) reflection = optionalBoolFlag{val: true} port = flags.Int("port", 0, prettify(` @@ -361,14 +364,15 @@ func main() { flags.Usage = usage flags.Parse(os.Args[1:]) - var gRPCOptions []string + var grpcCurlCmd []string + grpcCurlCmd = append(grpcCurlCmd, "grpcurl") for _, flagName := range grpcCurlFlags { f := flags.Lookup(flagName) if f.Value.String() != f.DefValue { if getter, ok := f.Value.(flag.Getter); ok && getter.Get() == true { - gRPCOptions = append(gRPCOptions, fmt.Sprintf("-%s", f.Name)) + grpcCurlCmd = append(grpcCurlCmd, fmt.Sprintf("-%s", f.Name)) } else { - gRPCOptions = append(gRPCOptions, fmt.Sprintf("-%s=%s", f.Name, strconv.Quote(f.Value.String()))) + grpcCurlCmd = append(grpcCurlCmd, fmt.Sprintf("-%s=%s", f.Name, strconv.Quote(f.Value.String()))) } } } @@ -654,7 +658,11 @@ func main() { handlerOpts = append(handlerOpts, configureJSandCSS(extraJS, standalone.AddJSFile)...) handlerOpts = append(handlerOpts, configureJSandCSS(extraCSS, standalone.AddCSSFile)...) handlerOpts = append(handlerOpts, configureAssets(otherAssets)...) - handlerOpts = append(handlerOpts, standalone.WithGRPCOptions(gRPCOptions)) + if overrideGRPCCurl != nil { + handlerOpts = append(handlerOpts, standalone.WithGRPCCmd([]string{*overrideGRPCCurl})) + } else { + handlerOpts = append(handlerOpts, standalone.WithGRPCCmd(grpcCurlCmd)) + } handler := standalone.Handler(cc, target, methods, allFiles, handlerOpts...) if *maxTime > 0 { diff --git a/internal/resources/webform/webform-template.html b/internal/resources/webform/webform-template.html index 5a97dac3..a76ff6eb 100644 --- a/internal/resources/webform/webform-template.html +++ b/internal/resources/webform/webform-template.html @@ -144,7 +144,7 @@

Response Trailers

]; window.target = {{ .Target }}; - window.gRPCurlOptions = {{ .GRPCurlOptions }}; + window.gRPCurlCmd = {{ .GRPCurlCmd }}; initGRPCForm(services, svcDescs, mtdDescs, '{{ .InvokeURI }}', '{{ .MetadataURI }}', {{ .Debug }}, headers); })(); diff --git a/internal/resources/webform/webform.js b/internal/resources/webform/webform.js index ede68566..d68745dc 100644 --- a/internal/resources/webform/webform.js +++ b/internal/resources/webform/webform.js @@ -2113,9 +2113,7 @@ window.initGRPCForm = function(services, svcDescs, mtdDescs, invokeURI, metadata let gRPCurlTextArea = $("#grpc-curl-text"); function updateCurlCommand(requestDataJson) { - const grpcOpts = window.gRPCurlOptions ? ' ' + window.gRPCurlOptions : ''; - - let metadataStr = ""; + let grpcCmd = window.gRPCurlCmd; const service = $("#grpc-service").val(); const method = $("#grpc-method").val(); @@ -2129,11 +2127,11 @@ window.initGRPCForm = function(services, svcDescs, mtdDescs, invokeURI, metadata const name = $(cells[0]).val(); const val = $(cells[1]).val(); if (name !== "") { - metadataStr += ` -H "${name}: ${val}"`; + grpcCmd += ` -H "${name}: ${val}"`; } } - gRPCurlTextArea.text(`grpcurl${grpcOpts}${metadataStr} -d '${requestDataJson}' ${window.target} ${service}.${method}`); + gRPCurlTextArea.text(`${grpcCmd} -d '${requestDataJson}' ${window.target} ${service}.${method}`); } var jsonRawTextArea = $("#grpc-request-raw-text"); diff --git a/standalone/opts.go b/standalone/opts.go index 4756aeb5..f73cf971 100644 --- a/standalone/opts.go +++ b/standalone/opts.go @@ -219,9 +219,15 @@ func WithClientDebug(debug bool) HandlerOption { }) } +func WithGRPCCmd(cmdLine []string) HandlerOption { + return optFunc(func(opts *handlerOptions) { + opts.gRPCurlCmd = cmdLine + }) +} + func WithGRPCOptions(options []string) HandlerOption { return optFunc(func(opts *handlerOptions) { - opts.gRPCurlOptions = options + opts.gRPCurlCmd = append([]string{"grpcurl"}, options...) }) } @@ -245,7 +251,7 @@ type handlerOptions struct { emitDefaults bool invokeVerbosity int debug *bool - gRPCurlOptions []string + gRPCurlCmd []string } func (opts *handlerOptions) addlServedResources() []*resource { diff --git a/standalone/standalone.go b/standalone/standalone.go index 44d032e0..897f17e8 100644 --- a/standalone/standalone.go +++ b/standalone/standalone.go @@ -45,10 +45,10 @@ const csrfHeaderName = "x-grpcui-csrf-token" // be handling a sub-path (e.g. handling "/rpc-ui/") then use http.StripPrefix. func Handler(ch grpcdynamic.Channel, target string, methods []*desc.MethodDescriptor, files []*desc.FileDescriptor, opts ...HandlerOption) http.Handler { uiOpts := &handlerOptions{ - indexTmpl: defaultIndexTemplate, - css: grpcui.WebFormSampleCSS(), - cssPublic: true, - gRPCurlOptions: nil, + indexTmpl: defaultIndexTemplate, + css: grpcui.WebFormSampleCSS(), + cssPublic: true, + gRPCurlCmd: []string{"grpcurl"}, } for _, o := range opts { o.apply(uiOpts) @@ -79,7 +79,7 @@ func Handler(ch grpcdynamic.Channel, target string, methods []*desc.MethodDescri formOpts := grpcui.WebFormOptions{ DefaultMetadata: uiOpts.defaultMetadata, Debug: uiOpts.debug, - GRPCurlOptions: uiOpts.gRPCurlOptions, + GRPCurlCmd: uiOpts.gRPCurlCmd, } webFormHTML := grpcui.WebFormContentsWithOptions("invoke", "metadata", target, methods, formOpts) indexContents := getIndexContents(uiOpts.indexTmpl, target, webFormHTML, uiOpts.tmplResources) diff --git a/webform.go b/webform.go index 3252e444..db261cf9 100644 --- a/webform.go +++ b/webform.go @@ -72,7 +72,7 @@ type WebFormOptions struct { // debug is enabled). Debug *bool // Any options that will be rendered before grpcurl in the grpccurl/raw request box - GRPCurlOptions []string + GRPCurlCmd []string } // WebFormContentsWithOptions is the same as WebFormContents except that it @@ -93,7 +93,7 @@ func WebFormContentsWithOptions(invokeURI, metadataURI string, target string, de DefaultMetadata []metadataEntry Debug bool Target string - GRPCurlOptions template.JS + GRPCurlCmd template.JS }{ InvokeURI: invokeURI, MetadataURI: metadataURI, @@ -104,11 +104,11 @@ func WebFormContentsWithOptions(invokeURI, metadataURI string, target string, de Target: target, } - gRPCOptionsJSONStr, err := json.Marshal(strings.Join(opts.GRPCurlOptions, " ")) + gRPCOptionsJSONStr, err := json.Marshal(strings.Join(opts.GRPCurlCmd, " ")) if err != nil { panic(fmt.Errorf("Error marshaling to JSON: %w", err)) } - params.GRPCurlOptions = template.JS(gRPCOptionsJSONStr) + params.GRPCurlCmd = template.JS(gRPCOptionsJSONStr) if opts.Debug != nil { params.Debug = *opts.Debug }