mirror of
https://github.com/foomo/gotsrpc.git
synced 2025-10-16 12:35:35 +00:00
fix: struct error
This commit is contained in:
parent
6f0cb501fa
commit
0a3551cb98
16
error.go
16
error.go
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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{}
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user