Repository: goadesign/goa
Pull request #3532 (2024-06-15 06:08:27)

Properly handle SkipRequestBodyEncodeDecode when generating CLI


Patch:
diff --git a/codegen/cli/cli.go b/codegen/cli/cli.go
index 3c3fc0f9..a69f7470 100644
--- a/codegen/cli/cli.go
+++ b/codegen/cli/cli.go
@@ -178,7 +178,7 @@ func BuildSubcommandData(svcName string, m *service.MethodData, buildFunction *B
 			description = fmt.Sprintf("Make request to the %q endpoint", m.Name)
 		}
 
-		if buildFunction == nil && len(flags) > 0 {
+		if m.Payload != "" && buildFunction == nil && len(flags) > 0 {
 			// No build function, just convert the arg to the body type
 			var convPre, convSuff string
 			target := "data"
diff --git a/grpc/codegen/client_cli.go b/grpc/codegen/client_cli.go
index 9a694738..20133cfe 100644
--- a/grpc/codegen/client_cli.go
+++ b/grpc/codegen/client_cli.go
@@ -222,8 +222,6 @@ func ParseEndpoint(cc *grpc.ClientConn, opts ...grpc.CallOption) (goa.Endpoint,
 				data, err = {{ $pkgName}}.{{ .BuildFunction.Name }}({{ range .BuildFunction.ActualParams }}*{{ . }}Flag, {{ end }})
 			{{- else if .Conversion }}
 				{{ .Conversion }}
-			{{- else }}
-				data = nil
 			{{- end }}
 		{{- end }}
 			}
diff --git a/http/codegen/templates/parse_endpoint.go.tpl b/http/codegen/templates/parse_endpoint.go.tpl
index c7bdcbd6..d967bcfd 100644
--- a/http/codegen/templates/parse_endpoint.go.tpl
+++ b/http/codegen/templates/parse_endpoint.go.tpl
@@ -41,8 +41,6 @@ func ParseEndpoint(
 				data, err = {{ $pkgName}}.{{ .BuildFunction.Name }}({{ range .BuildFunction.ActualParams }}*{{ . }}Flag, {{ end }})
 			{{- else if .Conversion }}
 				{{ .Conversion }}
-			{{- else }}
-				data = nil
 			{{- end }}
 			{{- if .StreamFlag }}
 				{{- if .BuildFunction }}


Test patch:
diff --git a/http/codegen/client_cli_test.go b/http/codegen/client_cli_test.go
index e771a8aa..dbef28cc 100644
--- a/http/codegen/client_cli_test.go
+++ b/http/codegen/client_cli_test.go
@@ -23,6 +23,7 @@ func TestClientCLIFiles(t *testing.T) {
 		{"simple-parse", testdata.MultiSimpleDSL, testdata.MultiSimpleParseCode, 0, 3},
 		{"multi-parse", testdata.MultiDSL, testdata.MultiParseCode, 0, 3},
 		{"multi-required-payload", testdata.MultiRequiredPayloadDSL, testdata.MultiRequiredPayloadParseCode, 0, 3},
+		{"skip-request-body-encode-decode", testdata.SkipRequestBodyEncodeDecodeDSL, testdata.SkipRequestBodyEncodeDecodeParseCode, 0, 3},
 		{"streaming-parse", testdata.StreamingMultipleServicesDSL, testdata.StreamingParseCode, 0, 3},
 		{"simple-build", testdata.MultiSimpleDSL, testdata.MultiSimpleBuildCode, 1, 1},
 		{"multi-build", testdata.MultiDSL, testdata.MultiBuildCode, 1, 1},
diff --git a/http/codegen/testdata/parse_endpoint_functions.go b/http/codegen/testdata/parse_endpoint_functions.go
index 4b5ff942..be2cf541 100644
--- a/http/codegen/testdata/parse_endpoint_functions.go
+++ b/http/codegen/testdata/parse_endpoint_functions.go
@@ -109,20 +109,16 @@ func ParseEndpoint(
 			switch epn {
 			case "method-service-no-payload11":
 				endpoint = c.MethodServiceNoPayload11()
-				data = nil
 			case "method-service-no-payload12":
 				endpoint = c.MethodServiceNoPayload12()
-				data = nil
 			}
 		case "service-multi-no-payload2":
 			c := servicemultinopayload2c.NewClient(scheme, host, doer, enc, dec, restore)
 			switch epn {
 			case "method-service-no-payload21":
 				endpoint = c.MethodServiceNoPayload21()
-				data = nil
 			case "method-service-no-payload22":
 				endpoint = c.MethodServiceNoPayload22()
-				data = nil
 			}
 		}
 	}
@@ -245,7 +241,6 @@ func ParseEndpoint(
 			switch epn {
 			case "method-multi-simple-no-payload":
 				endpoint = c.MethodMultiSimpleNoPayload()
-				data = nil
 			case "method-multi-simple-payload":
 				endpoint = c.MethodMultiSimplePayload()
 				data, err = servicemultisimple1c.BuildMethodMultiSimplePayloadPayload(*serviceMultiSimple1MethodMultiSimplePayloadBodyFlag)
@@ -255,7 +250,6 @@ func ParseEndpoint(
 			switch epn {
 			case "method-multi-simple-no-payload":
 				endpoint = c.MethodMultiSimpleNoPayload()
-				data = nil
 			case "method-multi-simple-payload":
 				endpoint = c.MethodMultiSimplePayload()
 				data, err = servicemultisimple2c.BuildMethodMultiSimplePayloadPayload(*serviceMultiSimple2MethodMultiSimplePayloadBodyFlag)
@@ -382,7 +376,6 @@ func ParseEndpoint(
 			switch epn {
 			case "method-multi-required-no-payload":
 				endpoint = c.MethodMultiRequiredNoPayload()
-				data = nil
 			case "method-multi-required-payload":
 				endpoint = c.MethodMultiRequiredPayload()
 				data, err = servicemultirequired2c.BuildMethodMultiRequiredPayloadPayload(*serviceMultiRequired2MethodMultiRequiredPayloadAFlag)
@@ -397,6 +390,100 @@ func ParseEndpoint(
 }
 `
 
+var SkipRequestBodyEncodeDecodeParseCode = `// ParseEndpoint returns the endpoint and payload as specified on the command
+// line.
+func ParseEndpoint(
+	scheme, host string,
+	doer goahttp.Doer,
+	enc func(*http.Request) goahttp.Encoder,
+	dec func(*http.Response) goahttp.Decoder,
+	restore bool,
+) (goa.Endpoint, any, error) {
+	var (
+		skipRequestBodyEncodeDecodeFlags = flag.NewFlagSet("skip-request-body-encode-decode", flag.ContinueOnError)
+
+		skipRequestBodyEncodeDecodeSkipRequestBodyEncodeDecodeMethodFlags      = flag.NewFlagSet("skip-request-body-encode-decode-method", flag.ExitOnError)
+		skipRequestBodyEncodeDecodeSkipRequestBodyEncodeDecodeMethodStreamFlag = skipRequestBodyEncodeDecodeSkipRequestBodyEncodeDecodeMethodFlags.String("stream", "REQUIRED", "path to file containing the streamed request body")
+	)
+	skipRequestBodyEncodeDecodeFlags.Usage = skipRequestBodyEncodeDecodeUsage
+	skipRequestBodyEncodeDecodeSkipRequestBodyEncodeDecodeMethodFlags.Usage = skipRequestBodyEncodeDecodeSkipRequestBodyEncodeDecodeMethodUsage
+
+	if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
+		return nil, nil, err
+	}
+
+	if flag.NArg() < 2 { // two non flag args are required: SERVICE and ENDPOINT (aka COMMAND)
+		return nil, nil, fmt.Errorf("not enough arguments")
+	}
+
+	var (
+		svcn string
+		svcf *flag.FlagSet
+	)
+	{
+		svcn = flag.Arg(0)
+		switch svcn {
+		case "skip-request-body-encode-decode":
+			svcf = skipRequestBodyEncodeDecodeFlags
+		default:
+			return nil, nil, fmt.Errorf("unknown service %q", svcn)
+		}
+	}
+	if err := svcf.Parse(flag.Args()[1:]); err != nil {
+		return nil, nil, err
+	}
+
+	var (
+		epn string
+		epf *flag.FlagSet
+	)
+	{
+		epn = svcf.Arg(0)
+		switch svcn {
+		case "skip-request-body-encode-decode":
+			switch epn {
+			case "skip-request-body-encode-decode-method":
+				epf = skipRequestBodyEncodeDecodeSkipRequestBodyEncodeDecodeMethodFlags
+
+			}
+
+		}
+	}
+	if epf == nil {
+		return nil, nil, fmt.Errorf("unknown %q endpoint %q", svcn, epn)
+	}
+
+	// Parse endpoint flags if any
+	if svcf.NArg() > 1 {
+		if err := epf.Parse(svcf.Args()[1:]); err != nil {
+			return nil, nil, err
+		}
+	}
+
+	var (
+		data     any
+		endpoint goa.Endpoint
+		err      error
+	)
+	{
+		switch svcn {
+		case "skip-request-body-encode-decode":
+			c := skiprequestbodyencodedecodec.NewClient(scheme, host, doer, enc, dec, restore)
+			switch epn {
+			case "skip-request-body-encode-decode-method":
+				endpoint = c.SkipRequestBodyEncodeDecodeMethod()
+				data, err = skiprequestbodyencodedecodec.BuildSkipRequestBodyEncodeDecodeMethodStreamPayload(*skipRequestBodyEncodeDecodeSkipRequestBodyEncodeDecodeMethodStreamFlag)
+			}
+		}
+	}
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return endpoint, data, nil
+}
+`
+
 var MultiParseCode = `// ParseEndpoint returns the endpoint and payload as specified on the command
 // line.
 func ParseEndpoint(
@@ -487,7 +574,6 @@ func ParseEndpoint(
 			switch epn {
 			case "method-multi-no-payload":
 				endpoint = c.MethodMultiNoPayload()
-				data = nil
 			case "method-multi-payload":
 				endpoint = c.MethodMultiPayload()
 				data, err = servicemultic.BuildMethodMultiPayloadPayload(*serviceMultiMethodMultiPayloadBodyFlag, *serviceMultiMethodMultiPayloadBFlag, *serviceMultiMethodMultiPayloadAFlag)
@@ -602,14 +688,12 @@ func ParseEndpoint(
 			switch epn {
 			case "method":
 				endpoint = c.Method()
-				data = nil
 			}
 		case "streaming-service-b":
 			c := streamingservicebc.NewClient(scheme, host, doer, enc, dec, restore, dialer, streamingServiceBConfigurer)
 			switch epn {
 			case "method":
 				endpoint = c.Method()
-				data = nil
 			}
 		}
 	}
diff --git a/http/codegen/testdata/streaming_dsls.go b/http/codegen/testdata/streaming_dsls.go
index 8e247a9b..153b5471 100644
--- a/http/codegen/testdata/streaming_dsls.go
+++ b/http/codegen/testdata/streaming_dsls.go
@@ -22,6 +22,18 @@ var MixedEndpointsDSL = func() {
 	})
 }
 
+var SkipRequestBodyEncodeDecodeDSL = func() {
+	Service("SkipRequestBodyEncodeDecode", func() {
+		Method("SkipRequestBodyEncodeDecodeMethod", func() {
+			HTTP(func() {
+				POST("/")
+				SkipRequestBodyEncodeDecode()
+				Response(StatusOK)
+			})
+		})
+	})
+}
+
 var StreamingMultipleServicesDSL = func() {
 	Service("StreamingServiceA", func() {
 		Method("Method", func() {