Repository: goadesign/goa
Pull request #2610 (2020-07-14 02:44:04)

Support GRPC error responses in API


Patch:
diff --git a/dsl/grpc.go b/dsl/grpc.go
index d49301e2..d89d88d0 100644
--- a/dsl/grpc.go
+++ b/dsl/grpc.go
@@ -58,7 +58,7 @@ const (
 // appear in the request or response types. The functions may also define new
 // attributes or override the existing request or response type attributes.
 //
-// GRPC must appear in a Service or a Method expression.
+// GRPC must appear in an API, a Service, or a Method expression.
 //
 // GRPC accepts a single argument which is the defining DSL function.
 //
@@ -92,6 +92,8 @@ const (
 //
 func GRPC(fn func()) {
 	switch actual := eval.Current().(type) {
+	case *expr.APIExpr:
+		eval.Execute(fn, expr.Root.API.GRPC)
 	case *expr.ServiceExpr:
 		res := expr.Root.API.GRPC.ServiceFor(actual)
 		res.DSLFunc = fn
diff --git a/dsl/http.go b/dsl/http.go
index 050c4835..f0147681 100644
--- a/dsl/http.go
+++ b/dsl/http.go
@@ -89,7 +89,7 @@ const (
 // header, parameter or body attributes inherit the properties of the attributes
 // with the same names that appear in the method payload or result types.
 //
-// HTTP must appear in API, a Service or an Method expression.
+// HTTP must appear in an API, a Service, or a Method expression.
 //
 // HTTP accepts an optional argument which is the defining DSL function.
 //
diff --git a/expr/grpc_endpoint.go b/expr/grpc_endpoint.go
index 88677657..83b8e034 100644
--- a/expr/grpc_endpoint.go
+++ b/expr/grpc_endpoint.go
@@ -85,6 +85,11 @@ func (e *GRPCEndpointExpr) Prepare() {
 	}
 	e.Response.Prepare()
 
+	// Prepare error response
+	for _, er := range e.GRPCErrors {
+		er.Response.Prepare()
+	}
+
 	// Inherit error only if it doesn't already exist in the endpoint errors
 	inherit := func(r *GRPCErrorExpr) {
 		found := false
@@ -95,6 +100,7 @@ func (e *GRPCEndpointExpr) Prepare() {
 			}
 		}
 		if !found {
+			r.Response.Prepare()
 			e.GRPCErrors = append(e.GRPCErrors, r.Dup())
 		}
 	}
@@ -105,11 +111,6 @@ func (e *GRPCEndpointExpr) Prepare() {
 	for _, r := range Root.API.GRPC.Errors {
 		inherit(r)
 	}
-
-	// Prepare error response
-	for _, er := range e.GRPCErrors {
-		er.Response.Prepare()
-	}
 }
 
 // Validate validates the endpoint expression by checking if the request
diff --git a/expr/grpc_error.go b/expr/grpc_error.go
index da2ac386..b387254e 100644
--- a/expr/grpc_error.go
+++ b/expr/grpc_error.go
@@ -51,7 +51,7 @@ func (e *GRPCErrorExpr) Finalize(a *GRPCEndpointExpr) {
 		ee = p.MethodExpr.Error(e.Name)
 	case *GRPCServiceExpr:
 		ee = p.Error(e.Name)
-	case *RootExpr:
+	case *GRPCExpr:
 		ee = Root.Error(e.Name)
 	}
 	e.ErrorExpr = ee
diff --git a/http/codegen/openapi/v3/builder.go b/http/codegen/openapi/v3/builder.go
index 8f773cda..57335683 100644
--- a/http/codegen/openapi/v3/builder.go
+++ b/http/codegen/openapi/v3/builder.go
@@ -110,6 +110,9 @@ func buildPaths(h *expr.HTTPExpr, bodies map[string]map[string]*EndpointBodies,
 		for _, e := range svc.HTTPEndpoints {
 			for _, r := range e.Routes {
 				for _, key := range r.FullPaths() {
+					// Remove any wildcards that is defined in path as a workaround to
+					// https://github.com/OAI/OpenAPI-Specification/issues/291
+					key = expr.HTTPWildcardRegex.ReplaceAllString(key, "/{$1}")
 					operation := buildOperation(key, r, sbod[e.Name()], api.Random())
 					path, ok := paths[key]
 					if !ok {


Test patch:
diff --git a/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file0.golden b/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file0.golden
index c8425959..96c7787c 100644
--- a/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file0.golden
+++ b/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file0.golden
@@ -1,1 +1,1 @@
-{"openapi":"3.0.3","info":{"title":"Goa API","version":"1.0"},"servers":[{"url":"localhost:80","description":"Default server for test api"}],"paths":{"/{*int_map}":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"int_map","in":"path","required":true,"schema":{"type":"integer","example":9176544974339886224,"format":"int64"},"example":1933576090881074823}],"responses":{"204":{"description":"","content":{"application/json":{"example":{}}}}}}}},"components":{}}
\ No newline at end of file
+{"openapi":"3.0.3","info":{"title":"Goa API","version":"1.0"},"servers":[{"url":"localhost:80","description":"Default server for test api"}],"paths":{"/{int_map}":{"post":{"tags":["test service"],"summary":"test endpoint test service","operationId":"test service#test endpoint","parameters":[{"name":"int_map","in":"path","required":true,"schema":{"type":"integer","example":9176544974339886224,"format":"int64"},"example":1933576090881074823}],"responses":{"204":{"description":"","content":{"application/json":{"example":{}}}}}}}},"components":{}}
\ No newline at end of file
diff --git a/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file1.golden b/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file1.golden
index 18352d20..13067662 100644
--- a/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file1.golden
+++ b/http/codegen/openapi/v3/testdata/golden/path-with-wildcards_file1.golden
@@ -6,7 +6,7 @@ servers:
 - url: localhost:80
   description: Default server for test api
 paths:
-  /{*int_map}:
+  /{int_map}:
     post:
       tags:
       - test service