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
|
// retrieve error details
|
||||||
errType := reflect.TypeOf(err)
|
errType := reflect.TypeOf(err)
|
||||||
|
errElem := errType
|
||||||
|
if errType.Kind() == reflect.Ptr {
|
||||||
|
errElem = errType.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
inst := &Error{
|
inst := &Error{
|
||||||
Msg: err.Error(),
|
Msg: err.Error(),
|
||||||
Type: errType.String(),
|
Type: errType.String(),
|
||||||
Pkg: errType.Elem().PkgPath(),
|
Pkg: errElem.PkgPath(),
|
||||||
Data: err,
|
Data: err,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +84,9 @@ func (e *Error) Format(s fmt.State, verb rune) {
|
|||||||
switch verb {
|
switch verb {
|
||||||
case 'v':
|
case 'v':
|
||||||
if s.Flag('+') {
|
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 {
|
if e.Data != nil {
|
||||||
fmt.Fprintf(s, "Data: %v\n", e.Data)
|
_, _ = fmt.Fprintf(s, "Data: %v\n", e.Data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -106,10 +110,14 @@ func (e *Error) Is(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errType := reflect.TypeOf(err)
|
errType := reflect.TypeOf(err)
|
||||||
|
errElem := errType
|
||||||
|
if errType.Kind() == reflect.Ptr {
|
||||||
|
errElem = errType.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
if e.Msg == err.Error() &&
|
if e.Msg == err.Error() &&
|
||||||
errType.String() == e.Type &&
|
errType.String() == e.Type &&
|
||||||
errType.Elem().PkgPath() == e.Pkg {
|
errElem.PkgPath() == e.Pkg {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,14 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
ScalarError string
|
ScalarError string
|
||||||
|
StructError struct {
|
||||||
|
Msg string
|
||||||
|
Map map[string]string
|
||||||
|
Slice []string
|
||||||
|
Struct struct {
|
||||||
|
A string
|
||||||
|
}
|
||||||
|
}
|
||||||
CustomError struct {
|
CustomError struct {
|
||||||
Msg string
|
Msg string
|
||||||
Map map[string]string
|
Map map[string]string
|
||||||
@ -33,6 +41,19 @@ func (e *ScalarError) Error() string {
|
|||||||
return string(*e)
|
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 {
|
func NewCustomError(msg string) *CustomError {
|
||||||
return &CustomError{
|
return &CustomError{
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
@ -86,6 +107,10 @@ func (h *Handler) TypedError(w http.ResponseWriter, r *http.Request) (e error) {
|
|||||||
return ErrTyped
|
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) {
|
func (h *Handler) ScalarError(w http.ResponseWriter, r *http.Request) (e error) {
|
||||||
return NewScalarError(ScalarErrorOne)
|
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 ----------------")
|
fmt.Println("--- CustomError ----------------")
|
||||||
var customErr *backend.CustomError
|
var customErr *backend.CustomError
|
||||||
|
|||||||
@ -17,6 +17,7 @@ const (
|
|||||||
ServiceGoTSRPCProxyScalar = "Scalar"
|
ServiceGoTSRPCProxyScalar = "Scalar"
|
||||||
ServiceGoTSRPCProxyScalarError = "ScalarError"
|
ServiceGoTSRPCProxyScalarError = "ScalarError"
|
||||||
ServiceGoTSRPCProxyStruct = "Struct"
|
ServiceGoTSRPCProxyStruct = "Struct"
|
||||||
|
ServiceGoTSRPCProxyStructError = "StructError"
|
||||||
ServiceGoTSRPCProxyTypedCustomError = "TypedCustomError"
|
ServiceGoTSRPCProxyTypedCustomError = "TypedCustomError"
|
||||||
ServiceGoTSRPCProxyTypedError = "TypedError"
|
ServiceGoTSRPCProxyTypedError = "TypedError"
|
||||||
ServiceGoTSRPCProxyTypedScalarError = "TypedScalarError"
|
ServiceGoTSRPCProxyTypedScalarError = "TypedScalarError"
|
||||||
@ -164,6 +165,24 @@ func (p *ServiceGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
gotsrpc.Monitor(w, r, args, rets, callStats)
|
gotsrpc.Monitor(w, r, args, rets, callStats)
|
||||||
return
|
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:
|
case ServiceGoTSRPCProxyTypedCustomError:
|
||||||
var (
|
var (
|
||||||
args []interface{}
|
args []interface{}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ type ServiceGoTSRPCClient interface {
|
|||||||
Scalar(ctx go_context.Context) (e *ScalarError, clientErr error)
|
Scalar(ctx go_context.Context) (e *ScalarError, clientErr error)
|
||||||
ScalarError(ctx go_context.Context) (e error, clientErr error)
|
ScalarError(ctx go_context.Context) (e error, clientErr error)
|
||||||
Struct(ctx go_context.Context) (e *StructError, 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)
|
TypedCustomError(ctx go_context.Context) (e error, clientErr error)
|
||||||
TypedError(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)
|
TypedScalarError(ctx go_context.Context) (e error, clientErr error)
|
||||||
@ -105,6 +106,16 @@ func (tsc *HTTPServiceGoTSRPCClient) Struct(ctx go_context.Context) (e *StructEr
|
|||||||
return
|
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) {
|
func (tsc *HTTPServiceGoTSRPCClient) TypedCustomError(ctx go_context.Context) (e error, clientErr error) {
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
reply := []interface{}{&e}
|
reply := []interface{}{&e}
|
||||||
|
|||||||
@ -54,6 +54,7 @@ type Service interface {
|
|||||||
Scalar(w http.ResponseWriter, r *http.Request) (e *ScalarError)
|
Scalar(w http.ResponseWriter, r *http.Request) (e *ScalarError)
|
||||||
MultiScalar(w http.ResponseWriter, r *http.Request) (e *MultiScalar)
|
MultiScalar(w http.ResponseWriter, r *http.Request) (e *MultiScalar)
|
||||||
Struct(w http.ResponseWriter, r *http.Request) (e *StructError)
|
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)
|
TypedError(w http.ResponseWriter, r *http.Request) (e error)
|
||||||
ScalarError(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)
|
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 {
|
if len(response) > 0 {
|
||||||
errResp := response[len(response)-1]
|
errResp := response[len(response)-1]
|
||||||
if v, ok := errResp.(error); ok && v != nil {
|
if v, ok := errResp.(error); ok && v != nil {
|
||||||
if !reflect.ValueOf(v).IsNil() {
|
if !reflect.ValueOf(v).IsZero() {
|
||||||
stats.ErrorCode = 1
|
stats.ErrorCode = 1
|
||||||
stats.ErrorType = fmt.Sprintf("%T", v)
|
stats.ErrorType = fmt.Sprintf("%T", v)
|
||||||
stats.ErrorMessage = v.Error()
|
stats.ErrorMessage = v.Error()
|
||||||
|
|||||||
@ -33,7 +33,7 @@ var msgpackClientHandle = &clientHandle{
|
|||||||
beforeEncodeReply: func(resp *[]interface{}) error {
|
beforeEncodeReply: func(resp *[]interface{}) error {
|
||||||
for k, v := range *resp {
|
for k, v := range *resp {
|
||||||
if e, ok := v.(error); ok {
|
if e, ok := v.(error); ok {
|
||||||
if r := reflect.ValueOf(e); !r.IsNil() {
|
if r := reflect.ValueOf(e); !r.IsZero() {
|
||||||
(*resp)[k] = NewError(e)
|
(*resp)[k] = NewError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,7 +43,11 @@ var msgpackClientHandle = &clientHandle{
|
|||||||
beforeDecodeReply: func(reply []interface{}) ([]interface{}, error) {
|
beforeDecodeReply: func(reply []interface{}) ([]interface{}, error) {
|
||||||
ret := make([]interface{}, len(reply))
|
ret := make([]interface{}, len(reply))
|
||||||
for k, v := range 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
|
var e *Error
|
||||||
ret[k] = e
|
ret[k] = e
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user