Repository: goadesign/goa
Pull request #3515 (2024-05-06 06:40:03)

 Fix OpenAPI v2 to not merge service params into endpoint headers
v3 is correct so I fixed v2 accordingly.

raphael: This is great, thank you!
tchssk: It's ready to merge.

Patch:
diff --git a/http/codegen/openapi/v2/builder.go b/http/codegen/openapi/v2/builder.go
index e94699c7..e8907ca8 100644
--- a/http/codegen/openapi/v2/builder.go
+++ b/http/codegen/openapi/v2/builder.go
@@ -294,29 +294,11 @@ func paramsFromExpr(params *expr.MappedAttributeExpr, path string) []*Parameter
 func paramsFromHeaders(endpoint *expr.HTTPEndpointExpr) []*Parameter {
 	var params []*Parameter
 
-	var (
-		rma = endpoint.Service.Params
-		ma  = endpoint.Headers
-
-		merged *expr.MappedAttributeExpr
-	)
-	{
-		if rma == nil {
-			merged = ma
-		} else if ma == nil {
-			merged = rma
-		} else {
-			merged = expr.DupMappedAtt(rma)
-			merged.Merge(ma)
-		}
-	}
-
-	for _, n := range *expr.AsObject(merged.Type) {
-		header := n.Attribute
-		required := merged.IsRequiredNoDefault(n.Name)
-		p := paramFor(header, merged.ElemName(n.Name), "header", required)
-		params = append(params, p)
-	}
+	expr.WalkMappedAttr(endpoint.Headers, func(name, elem string, att *expr.AttributeExpr) error { // nolint: errcheck
+		required := endpoint.Headers.IsRequiredNoDefault(name)
+		params = append(params, paramFor(att, elem, "header", required))
+		return nil
+	})
 
 	// Add basic auth to headers
 	if att := expr.TaggedAttribute(endpoint.MethodExpr.Payload, "security:username"); att != "" {


Test patch:
diff --git a/http/codegen/openapi/v2/files_test.go b/http/codegen/openapi/v2/files_test.go
index 3c4f5988..f77f28c4 100644
--- a/http/codegen/openapi/v2/files_test.go
+++ b/http/codegen/openapi/v2/files_test.go
@@ -40,6 +40,9 @@ func TestSections(t *testing.T) {
 		{"with-spaces", testdata.WithSpacesDSL},
 		{"with-map", testdata.WithMapDSL},
 		{"path-with-wildcards", testdata.PathWithWildcardDSL},
+		{"path-with-multiple-wildcards", testdata.PathWithMultipleWildcardDSL},
+		{"path-with-multiple-explicit-wildcards", testdata.PathWithMultipleExplicitWildcardDSL},
+		{"headers", testdata.HeadersDSL},
 		{"typename", testdata.TypenameDSL},
 		{"not-generate-server", testdata.NotGenerateServerDSL},
 		{"not-generate-host", testdata.NotGenerateHostDSL},
diff --git a/http/codegen/openapi/v2/testdata/TestSections/headers_file0.golden b/http/codegen/openapi/v2/testdata/TestSections/headers_file0.golden
new file mode 100644
index 00000000..075b095a
--- /dev/null
+++ b/http/codegen/openapi/v2/testdata/TestSections/headers_file0.golden
@@ -0,0 +1,1 @@
+{"swagger":"2.0","info":{"title":"","version":"0.0.1"},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"foo","in":"header","required":false,"type":"integer"},{"name":"bar","in":"header","required":false,"type":"integer"}],"responses":{"204":{"description":"No Content response."}},"schemes":["http"]}}}}
\ No newline at end of file
diff --git a/http/codegen/openapi/v2/testdata/TestSections/headers_file1.golden b/http/codegen/openapi/v2/testdata/TestSections/headers_file1.golden
new file mode 100644
index 00000000..d26977bd
--- /dev/null
+++ b/http/codegen/openapi/v2/testdata/TestSections/headers_file1.golden
@@ -0,0 +1,34 @@
+swagger: "2.0"
+info:
+    title: ""
+    version: 0.0.1
+host: localhost:80
+consumes:
+    - application/json
+    - application/xml
+    - application/gob
+produces:
+    - application/json
+    - application/xml
+    - application/gob
+paths:
+    /:
+        post:
+            tags:
+                - test service
+            summary: test endpoint test service
+            operationId: test service#test endpoint
+            parameters:
+                - name: foo
+                  in: header
+                  required: false
+                  type: integer
+                - name: bar
+                  in: header
+                  required: false
+                  type: integer
+            responses:
+                "204":
+                    description: No Content response.
+            schemes:
+                - http
diff --git a/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-explicit-wildcards_file0.golden b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-explicit-wildcards_file0.golden
new file mode 100644
index 00000000..186f6c7a
--- /dev/null
+++ b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-explicit-wildcards_file0.golden
@@ -0,0 +1,1 @@
+{"swagger":"2.0","info":{"title":"","version":"0.0.1"},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/{foo}/{bar}":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"foo","in":"path","required":true,"type":"integer"},{"name":"bar","in":"path","required":true,"type":"integer"}],"responses":{"204":{"description":"No Content response."}},"schemes":["http"]}}}}
\ No newline at end of file
diff --git a/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-explicit-wildcards_file1.golden b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-explicit-wildcards_file1.golden
new file mode 100644
index 00000000..c0b317c3
--- /dev/null
+++ b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-explicit-wildcards_file1.golden
@@ -0,0 +1,34 @@
+swagger: "2.0"
+info:
+    title: ""
+    version: 0.0.1
+host: localhost:80
+consumes:
+    - application/json
+    - application/xml
+    - application/gob
+produces:
+    - application/json
+    - application/xml
+    - application/gob
+paths:
+    /{foo}/{bar}:
+        post:
+            tags:
+                - test service
+            summary: test endpoint test service
+            operationId: test service#test endpoint
+            parameters:
+                - name: foo
+                  in: path
+                  required: true
+                  type: integer
+                - name: bar
+                  in: path
+                  required: true
+                  type: integer
+            responses:
+                "204":
+                    description: No Content response.
+            schemes:
+                - http
diff --git a/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-wildcards_file0.golden b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-wildcards_file0.golden
new file mode 100644
index 00000000..186f6c7a
--- /dev/null
+++ b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-wildcards_file0.golden
@@ -0,0 +1,1 @@
+{"swagger":"2.0","info":{"title":"","version":"0.0.1"},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/{foo}/{bar}":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"foo","in":"path","required":true,"type":"integer"},{"name":"bar","in":"path","required":true,"type":"integer"}],"responses":{"204":{"description":"No Content response."}},"schemes":["http"]}}}}
\ No newline at end of file
diff --git a/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-wildcards_file1.golden b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-wildcards_file1.golden
new file mode 100644
index 00000000..c0b317c3
--- /dev/null
+++ b/http/codegen/openapi/v2/testdata/TestSections/path-with-multiple-wildcards_file1.golden
@@ -0,0 +1,34 @@
+swagger: "2.0"
+info:
+    title: ""
+    version: 0.0.1
+host: localhost:80
+consumes:
+    - application/json
+    - application/xml
+    - application/gob
+produces:
+    - application/json
+    - application/xml
+    - application/gob
+paths:
+    /{foo}/{bar}:
+        post:
+            tags:
+                - test service
+            summary: test endpoint test service
+            operationId: test service#test endpoint
+            parameters:
+                - name: foo
+                  in: path
+                  required: true
+                  type: integer
+                - name: bar
+                  in: path
+                  required: true
+                  type: integer
+            responses:
+                "204":
+                    description: No Content response.
+            schemes:
+                - http
diff --git a/http/codegen/openapi/v3/files_test.go b/http/codegen/openapi/v3/files_test.go
index b15ddc4b..f68bbd3c 100644
--- a/http/codegen/openapi/v3/files_test.go
+++ b/http/codegen/openapi/v3/files_test.go
@@ -42,6 +42,9 @@ func TestFiles(t *testing.T) {
 		{"with-spaces", testdata.WithSpacesDSL},
 		{"with-map", testdata.WithMapDSL},
 		{"path-with-wildcards", testdata.PathWithWildcardDSL},
+		{"path-with-multiple-wildcards", testdata.PathWithMultipleWildcardDSL},
+		{"path-with-multiple-explicit-wildcards", testdata.PathWithMultipleExplicitWildcardDSL},
+		{"headers", testdata.HeadersDSL},
 		{"with-tags", testdata.WithTagsDSL},
 		{"with-tags-swagger", testdata.WithTagsSwaggerDSL},
 		{"typename", testdata.TypenameDSL},
diff --git a/http/codegen/openapi/v3/testdata/golden/headers_file0.golden b/http/codegen/openapi/v3/testdata/golden/headers_file0.golden
new file mode 100644
index 00000000..1dc7ed71
--- /dev/null
+++ b/http/codegen/openapi/v3/testdata/golden/headers_file0.golden
@@ -0,0 +1,1 @@
+{"openapi":"3.0.3","info":{"title":"Goa API","version":"0.0.1"},"servers":[{"url":"http://localhost:80","description":"Default server for test api"}],"paths":{"/":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"foo","in":"header","allowEmptyValue":true,"schema":{"type":"integer","example":9176544974339886224,"format":"int64"},"example":1933576090881074823},{"name":"bar","in":"header","allowEmptyValue":true,"schema":{"type":"integer","example":2166276375441812184,"format":"int64"},"example":7595816812588075382}],"responses":{"204":{"description":"No Content response."}}}}},"components":{},"tags":[{"name":"test service"}]}
\ No newline at end of file
diff --git a/http/codegen/openapi/v3/testdata/golden/headers_file1.golden b/http/codegen/openapi/v3/testdata/golden/headers_file1.golden
new file mode 100644
index 00000000..14eeba00
--- /dev/null
+++ b/http/codegen/openapi/v3/testdata/golden/headers_file1.golden
@@ -0,0 +1,37 @@
+openapi: 3.0.3
+info:
+    title: Goa API
+    version: 0.0.1
+servers:
+    - url: http://localhost:80
+      description: Default server for test api
+paths:
+    /:
+        post:
+            tags:
+                - test service
+            summary: test endpoint test service
+            operationId: test service#test endpoint
+            parameters:
+                - name: foo
+                  in: header
+                  allowEmptyValue: true
+                  schema:
+                    type: integer
+                    example: 9176544974339886224
+                    format: int64
+                  example: 1933576090881074823
+                - name: bar
+                  in: header
+                  allowEmptyValue: true
+                  schema:
+                    type: integer
+                    example: 2166276375441812184
+                    format: int64
+                  example: 7595816812588075382
+            responses:
+                "204":
+                    description: No Content response.
+components: {}
+tags:
+    - name: test service
diff --git a/http/codegen/openapi/v3/testdata/golden/path-with-multiple-explicit-wildcards_file0.golden b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-explicit-wildcards_file0.golden
new file mode 100644
index 00000000..9de239f5
--- /dev/null
+++ b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-explicit-wildcards_file0.golden
@@ -0,0 +1,1 @@
+{"openapi":"3.0.3","info":{"title":"Goa API","version":"0.0.1"},"servers":[{"url":"http://localhost:80","description":"Default server for test api"}],"paths":{"/{foo}/{bar}":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"foo","in":"path","required":true,"schema":{"type":"integer","example":9176544974339886224,"format":"int64"},"example":1933576090881074823},{"name":"bar","in":"path","required":true,"schema":{"type":"integer","example":2166276375441812184,"format":"int64"},"example":7595816812588075382}],"responses":{"204":{"description":"No Content response."}}}}},"components":{},"tags":[{"name":"test service"}]}
\ No newline at end of file
diff --git a/http/codegen/openapi/v3/testdata/golden/path-with-multiple-explicit-wildcards_file1.golden b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-explicit-wildcards_file1.golden
new file mode 100644
index 00000000..c780651e
--- /dev/null
+++ b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-explicit-wildcards_file1.golden
@@ -0,0 +1,37 @@
+openapi: 3.0.3
+info:
+    title: Goa API
+    version: 0.0.1
+servers:
+    - url: http://localhost:80
+      description: Default server for test api
+paths:
+    /{foo}/{bar}:
+        post:
+            tags:
+                - test service
+            summary: test endpoint test service
+            operationId: test service#test endpoint
+            parameters:
+                - name: foo
+                  in: path
+                  required: true
+                  schema:
+                    type: integer
+                    example: 9176544974339886224
+                    format: int64
+                  example: 1933576090881074823
+                - name: bar
+                  in: path
+                  required: true
+                  schema:
+                    type: integer
+                    example: 2166276375441812184
+                    format: int64
+                  example: 7595816812588075382
+            responses:
+                "204":
+                    description: No Content response.
+components: {}
+tags:
+    - name: test service
diff --git a/http/codegen/openapi/v3/testdata/golden/path-with-multiple-wildcards_file0.golden b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-wildcards_file0.golden
new file mode 100644
index 00000000..9de239f5
--- /dev/null
+++ b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-wildcards_file0.golden
@@ -0,0 +1,1 @@
+{"openapi":"3.0.3","info":{"title":"Goa API","version":"0.0.1"},"servers":[{"url":"http://localhost:80","description":"Default server for test api"}],"paths":{"/{foo}/{bar}":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"foo","in":"path","required":true,"schema":{"type":"integer","example":9176544974339886224,"format":"int64"},"example":1933576090881074823},{"name":"bar","in":"path","required":true,"schema":{"type":"integer","example":2166276375441812184,"format":"int64"},"example":7595816812588075382}],"responses":{"204":{"description":"No Content response."}}}}},"components":{},"tags":[{"name":"test service"}]}
\ No newline at end of file
diff --git a/http/codegen/openapi/v3/testdata/golden/path-with-multiple-wildcards_file1.golden b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-wildcards_file1.golden
new file mode 100644
index 00000000..c780651e
--- /dev/null
+++ b/http/codegen/openapi/v3/testdata/golden/path-with-multiple-wildcards_file1.golden
@@ -0,0 +1,37 @@
+openapi: 3.0.3
+info:
+    title: Goa API
+    version: 0.0.1
+servers:
+    - url: http://localhost:80
+      description: Default server for test api
+paths:
+    /{foo}/{bar}:
+        post:
+            tags:
+                - test service
+            summary: test endpoint test service
+            operationId: test service#test endpoint
+            parameters:
+                - name: foo
+                  in: path
+                  required: true
+                  schema:
+                    type: integer
+                    example: 9176544974339886224
+                    format: int64
+                  example: 1933576090881074823
+                - name: bar
+                  in: path
+                  required: true
+                  schema:
+                    type: integer
+                    example: 2166276375441812184
+                    format: int64
+                  example: 7595816812588075382
+            responses:
+                "204":
+                    description: No Content response.
+components: {}
+tags:
+    - name: test service
diff --git a/http/codegen/testdata/openapi_dsls.go b/http/codegen/testdata/openapi_dsls.go
index e831ba3d..3619a09c 100644
--- a/http/codegen/testdata/openapi_dsls.go
+++ b/http/codegen/testdata/openapi_dsls.go
@@ -535,6 +535,60 @@ var PathWithWildcardDSL = func() {
 	})
 }
 
+var PathWithMultipleWildcardDSL = func() {
+	Service("test service", func() {
+		Method("test endpoint", func() {
+			Payload(func() {
+				Attribute("foo", Int)
+				Attribute("bar", Int)
+			})
+			HTTP(func() {
+				POST("/{bar}")
+			})
+		})
+		HTTP(func() {
+			Path("/{foo}")
+		})
+	})
+}
+
+var PathWithMultipleExplicitWildcardDSL = func() {
+	Service("test service", func() {
+		Method("test endpoint", func() {
+			Payload(func() {
+				Attribute("foo", Int)
+				Attribute("bar", Int)
+			})
+			HTTP(func() {
+				POST("/{bar}")
+				Param("bar")
+			})
+		})
+		HTTP(func() {
+			Path("/{foo}")
+			Param("foo")
+		})
+	})
+}
+
+var HeadersDSL = func() {
+	Service("test service", func() {
+		Method("test endpoint", func() {
+			Payload(func() {
+				Attribute("foo", Int)
+				Attribute("bar", Int)
+			})
+			HTTP(func() {
+				POST("/")
+				Header("bar")
+			})
+		})
+		HTTP(func() {
+			Header("foo")
+		})
+	})
+}
+
 var WithTagsDSL = func() {
 	Service("test service", func() {
 		HTTP(func() {