Repository: goadesign/goa
Pull request #2871 (2021-06-12 05:43:59)

Finalize expr.RootExpr.Errors
#2867 Case 1

This pull request fixes to `expr.RootExpr` to finalize its Errors.

raphael: This is great, thank you!

Patch:
diff --git a/expr/root.go b/expr/root.go
index 92cea3ab..32e739ce 100644
--- a/expr/root.go
+++ b/expr/root.go
@@ -234,6 +234,9 @@ func (r *RootExpr) Finalize() {
 	if len(r.API.Servers) == 0 {
 		r.API.Servers = []*ServerExpr{r.API.DefaultServer()}
 	}
+	for _, e := range r.Errors {
+		e.Finalize()
+	}
 	for _, s := range r.API.Servers {
 		s.Finalize()
 	}


Test patch:
diff --git a/http/codegen/server_error_encoder_test.go b/http/codegen/server_error_encoder_test.go
index 445d2ee0..837f848c 100644
--- a/http/codegen/server_error_encoder_test.go
+++ b/http/codegen/server_error_encoder_test.go
@@ -15,7 +15,8 @@ func TestEncodeError(t *testing.T) {
 		Code string
 	}{
 		{"primitive-error-response", testdata.PrimitiveErrorResponseDSL, testdata.PrimitiveErrorResponseEncoderCode},
-		{"primitive-error-response", testdata.PrimitiveErrorInResponseHeaderDSL, testdata.PrimitiveErrorInResponseHeaderEncoderCode},
+		{"primitive-error-in-response-header", testdata.PrimitiveErrorInResponseHeaderDSL, testdata.PrimitiveErrorInResponseHeaderEncoderCode},
+		{"api-primitive-error-response", testdata.APIPrimitiveErrorResponseDSL, testdata.APIPrimitiveErrorResponseEncoderCode},
 		{"default-error-response", testdata.DefaultErrorResponseDSL, testdata.DefaultErrorResponseEncoderCode},
 		{"default-error-response-with-content-type", testdata.DefaultErrorResponseWithContentTypeDSL, testdata.DefaultErrorResponseWithContentTypeEncoderCode},
 		{"service-error-response", testdata.ServiceErrorResponseDSL, testdata.ServiceErrorResponseEncoderCode},
diff --git a/http/codegen/testdata/error_encoder_code.go b/http/codegen/testdata/error_encoder_code.go
index 7c675d41..22901630 100644
--- a/http/codegen/testdata/error_encoder_code.go
+++ b/http/codegen/testdata/error_encoder_code.go
@@ -80,6 +80,48 @@ func EncodeMethodPrimitiveErrorInResponseHeaderError(encoder func(context.Contex
 }
 `
 
+var APIPrimitiveErrorResponseEncoderCode = `// EncodeMethodAPIPrimitiveErrorResponseError returns an encoder for errors
+// returned by the MethodAPIPrimitiveErrorResponse
+// ServiceAPIPrimitiveErrorResponse endpoint.
+func EncodeMethodAPIPrimitiveErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
+	encodeError := goahttp.ErrorEncoder(encoder, formatter)
+	return func(ctx context.Context, w http.ResponseWriter, v error) error {
+		en, ok := v.(ErrorNamer)
+		if !ok {
+			return encodeError(ctx, w, v)
+		}
+		switch en.ErrorName() {
+		case "internal_error":
+			res := v.(*goa.ServiceError)
+			enc := encoder(ctx, w)
+			var body interface{}
+			if formatter != nil {
+				body = formatter(res)
+			} else {
+				body = NewMethodAPIPrimitiveErrorResponseInternalErrorResponseBody(res)
+			}
+			w.Header().Set("goa-error", res.ErrorName())
+			w.WriteHeader(http.StatusInternalServerError)
+			return enc.Encode(body)
+		case "bad_request":
+			res := v.(serviceapiprimitiveerrorresponse.BadRequest)
+			enc := encoder(ctx, w)
+			var body interface{}
+			if formatter != nil {
+				body = formatter(res)
+			} else {
+				body = NewMethodAPIPrimitiveErrorResponseBadRequestResponseBody(res)
+			}
+			w.Header().Set("goa-error", res.ErrorName())
+			w.WriteHeader(http.StatusBadRequest)
+			return enc.Encode(body)
+		default:
+			return encodeError(ctx, w, v)
+		}
+	}
+}
+`
+
 var DefaultErrorResponseEncoderCode = `// EncodeMethodDefaultErrorResponseError returns an encoder for errors returned
 // by the MethodDefaultErrorResponse ServiceDefaultErrorResponse endpoint.
 func EncodeMethodDefaultErrorResponseError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
diff --git a/http/codegen/testdata/error_response_dsls.go b/http/codegen/testdata/error_response_dsls.go
index ae4d214e..3ca89af4 100644
--- a/http/codegen/testdata/error_response_dsls.go
+++ b/http/codegen/testdata/error_response_dsls.go
@@ -62,6 +62,25 @@ var PrimitiveErrorInResponseHeaderDSL = func() {
 	})
 }
 
+var APIPrimitiveErrorResponseDSL = func() {
+	var _ = API("test", func() {
+		Error("bad_request", String)
+		HTTP(func() {
+			Response(StatusBadRequest, "bad_request")
+		})
+	})
+	Service("ServiceAPIPrimitiveErrorResponse", func() {
+		Method("MethodAPIPrimitiveErrorResponse", func() {
+			Error("bad_request", String)
+			Error("internal_error")
+			HTTP(func() {
+				GET("/one/two")
+				Response("internal_error", StatusInternalServerError)
+			})
+		})
+	})
+}
+
 var ServiceErrorResponseDSL = func() {
 	Service("ServiceServiceErrorResponse", func() {
 		Error("bad_request")