-
-
Notifications
You must be signed in to change notification settings - Fork 574
Description
I suspect there is an error in generation of the Encode/Decode...Error functions. See the example below.
When I look at the generated code, I see that formatter(ctx, res)
gets the casted type res
(cm.CustodianError
) (our error type on the method).
-
This is problematic when you return a wrapped error from the endpoint: i.e. wrapping
cm.CustodianError
to be able to do custom stuff in a customformatter
(e.g.v
is anerror
whichUnwrap
s tocm.CustodianError
etc). -
IMO: it should receive
v
, beforeUnwrap
inAs(v, &res)
such that theformatter
has a chance to actually read a wrapped type. -
From a design perspective I dont understand yet why
body = formatter(ctx, res)
returns agoahttp.Statuser
because
the returned interfacegoahttp.Statuser
is not used as the status is forcefully set (see below):
Maybeformatter
needs to be extended to be something like:type ErrorFormatter interface { MarshalToStatuser(ctx context.Context, v any) goahttp.Statuser Marshal(ctx context.Context, v any) any }
-
Also problematic is that
errors.As(v, &res)
is not checked and just panics (should be a debug assert).
Encode/Decode Generated:
func EncodeGetContractError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, 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 {
var en goa.GoaErrorNamer
if !errors.As(v, &en) {
return encodeError(ctx, w, v)
}
switch en.GoaErrorName() {
case "cm#not-found":
var res *cm.CustodianError
errors.As(v, &res)
enc := encoder(ctx, w)
var body any
if formatter != nil {
body = formatter(ctx, res)
} else {
body = NewGetContractCmNotFoundResponseBody(res)
}
w.Header().Set("goa-error", res.GoaErrorName())
w.WriteHeader(http.StatusNotFound)
return enc.Encode(body)