fix: struct error

This commit is contained in:
Kevin Franklin Kim 2025-03-06 16:08:43 +01:00
parent 6f0cb501fa
commit 0a3551cb98
No known key found for this signature in database
8 changed files with 97 additions and 7 deletions

View File

@ -34,11 +34,15 @@ func NewError(err error) *Error {
// retrieve error details
errType := reflect.TypeOf(err)
errElem := errType
if errType.Kind() == reflect.Ptr {
errElem = errType.Elem()
}
inst := &Error{
Msg: err.Error(),
Type: errType.String(),
Pkg: errType.Elem().PkgPath(),
Pkg: errElem.PkgPath(),
Data: err,
}
@ -80,9 +84,9 @@ func (e *Error) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%s.(%s)\n", e.Pkg, e.Type)
_, _ = fmt.Fprintf(s, "%s.(%s)\n", e.Pkg, e.Type)
if e.Data != nil {
fmt.Fprintf(s, "Data: %v\n", e.Data)
_, _ = fmt.Fprintf(s, "Data: %v\n", e.Data)
}
}
fallthrough
@ -106,10 +110,14 @@ func (e *Error) Is(err error) bool {
}
errType := reflect.TypeOf(err)
errElem := errType
if errType.Kind() == reflect.Ptr {
errElem = errType.Elem()
}
if e.Msg == err.Error() &&
errType.String() == e.Type &&
errType.Elem().PkgPath() == e.Pkg {
errElem.PkgPath() == e.Pkg {
return true
}

View File

@ -10,6 +10,14 @@ import (
type (
ScalarError string
StructError struct {
Msg string
Map map[string]string
Slice []string
Struct struct {
A string
}
}
CustomError struct {
Msg string
Map map[string]string
@ -33,6 +41,19 @@ func (e *ScalarError) Error() string {
return string(*e)
}
func NewStructError(msg string) StructError {
return StructError{
Msg: msg,
Map: map[string]string{"a": "b"},
Slice: []string{"a", "b"},
Struct: struct{ A string }{A: "b"},
}
}
func (e StructError) Error() string {
return e.Msg
}
func NewCustomError(msg string) *CustomError {
return &CustomError{
Msg: msg,
@ -86,6 +107,10 @@ func (h *Handler) TypedError(w http.ResponseWriter, r *http.Request) (e error) {
return ErrTyped
}
func (h *Handler) StructError(w http.ResponseWriter, r *http.Request) (e error) {
return NewStructError("struct error")
}
func (h *Handler) ScalarError(w http.ResponseWriter, r *http.Request) (e error) {
return NewScalarError(ScalarErrorOne)
}

View File

@ -147,6 +147,28 @@ func call() {
}
}
{
fmt.Println("--- StructError ----------------")
var structErr backend.StructError
var gotsrpcErr *gotsrpc.Error
serviceErr, err := c.StructError(ctx)
if err != nil {
panic("client error should be nil")
} else if serviceErr == nil {
panic("service error should not be nil")
} else if serviceErr != nil {
fmt.Printf("%s\n", serviceErr)
fmt.Printf("%q\n", serviceErr)
fmt.Printf("%+v\n", serviceErr)
}
if errors.As(serviceErr, &gotsrpcErr) {
fmt.Println(gotsrpcErr)
}
if errors.As(serviceErr, &structErr) {
fmt.Println(structErr)
}
}
{
fmt.Println("--- CustomError ----------------")
var customErr *backend.CustomError

View File

@ -17,6 +17,7 @@ const (
ServiceGoTSRPCProxyScalar = "Scalar"
ServiceGoTSRPCProxyScalarError = "ScalarError"
ServiceGoTSRPCProxyStruct = "Struct"
ServiceGoTSRPCProxyStructError = "StructError"
ServiceGoTSRPCProxyTypedCustomError = "TypedCustomError"
ServiceGoTSRPCProxyTypedError = "TypedError"
ServiceGoTSRPCProxyTypedScalarError = "TypedScalarError"
@ -164,6 +165,24 @@ func (p *ServiceGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
}
gotsrpc.Monitor(w, r, args, rets, callStats)
return
case ServiceGoTSRPCProxyStructError:
var (
args []interface{}
rets []interface{}
)
executionStart := time.Now()
rw := gotsrpc.ResponseWriter{ResponseWriter: w}
structErrorE := p.service.StructError(&rw, r)
callStats.Execution = time.Since(executionStart)
if rw.Status() == http.StatusOK {
rets = []interface{}{structErrorE}
if err := gotsrpc.Reply(rets, callStats, r, w); err != nil {
gotsrpc.ErrorCouldNotReply(w)
return
}
}
gotsrpc.Monitor(w, r, args, rets, callStats)
return
case ServiceGoTSRPCProxyTypedCustomError:
var (
args []interface{}

View File

@ -17,6 +17,7 @@ type ServiceGoTSRPCClient interface {
Scalar(ctx go_context.Context) (e *ScalarError, clientErr error)
ScalarError(ctx go_context.Context) (e error, clientErr error)
Struct(ctx go_context.Context) (e *StructError, clientErr error)
StructError(ctx go_context.Context) (e error, clientErr error)
TypedCustomError(ctx go_context.Context) (e error, clientErr error)
TypedError(ctx go_context.Context) (e error, clientErr error)
TypedScalarError(ctx go_context.Context) (e error, clientErr error)
@ -105,6 +106,16 @@ func (tsc *HTTPServiceGoTSRPCClient) Struct(ctx go_context.Context) (e *StructEr
return
}
func (tsc *HTTPServiceGoTSRPCClient) StructError(ctx go_context.Context) (e error, clientErr error) {
args := []interface{}{}
reply := []interface{}{&e}
clientErr = tsc.Client.Call(ctx, tsc.URL, tsc.EndPoint, "StructError", args, reply)
if clientErr != nil {
clientErr = pkg_errors.WithMessage(clientErr, "failed to call backend.ServiceGoTSRPCProxy StructError")
}
return
}
func (tsc *HTTPServiceGoTSRPCClient) TypedCustomError(ctx go_context.Context) (e error, clientErr error) {
args := []interface{}{}
reply := []interface{}{&e}

View File

@ -54,6 +54,7 @@ type Service interface {
Scalar(w http.ResponseWriter, r *http.Request) (e *ScalarError)
MultiScalar(w http.ResponseWriter, r *http.Request) (e *MultiScalar)
Struct(w http.ResponseWriter, r *http.Request) (e *StructError)
StructError(w http.ResponseWriter, r *http.Request) (e error)
TypedError(w http.ResponseWriter, r *http.Request) (e error)
ScalarError(w http.ResponseWriter, r *http.Request) (e error)
CustomError(w http.ResponseWriter, r *http.Request) (e error)

View File

@ -120,7 +120,7 @@ func Reply(response []interface{}, stats *CallStats, r *http.Request, w http.Res
if len(response) > 0 {
errResp := response[len(response)-1]
if v, ok := errResp.(error); ok && v != nil {
if !reflect.ValueOf(v).IsNil() {
if !reflect.ValueOf(v).IsZero() {
stats.ErrorCode = 1
stats.ErrorType = fmt.Sprintf("%T", v)
stats.ErrorMessage = v.Error()

View File

@ -33,7 +33,7 @@ var msgpackClientHandle = &clientHandle{
beforeEncodeReply: func(resp *[]interface{}) error {
for k, v := range *resp {
if e, ok := v.(error); ok {
if r := reflect.ValueOf(e); !r.IsNil() {
if r := reflect.ValueOf(e); !r.IsZero() {
(*resp)[k] = NewError(e)
}
}
@ -43,7 +43,11 @@ var msgpackClientHandle = &clientHandle{
beforeDecodeReply: func(reply []interface{}) ([]interface{}, error) {
ret := make([]interface{}, len(reply))
for k, v := range reply {
if reflect.TypeOf(v).Elem().Implements(errorType) {
val := reflect.TypeOf(v)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
if val.Implements(errorType) {
var e *Error
ret[k] = e
} else {