fix: remove unsafe pointer

This commit is contained in:
Kevin Franklin Kim 2022-07-18 16:08:20 +02:00
parent 16baabced1
commit 195d85e505
6 changed files with 75 additions and 13 deletions

View File

@ -75,6 +75,13 @@ func (h *Handler) MultiScalar(w http.ResponseWriter, r *http.Request) (e *backen
} }
} }
func (h *Handler) Struct(w http.ResponseWriter, r *http.Request) (e *backend.Struct) {
return &backend.Struct{
Message: "my custom scalar",
Data: "hello world",
}
}
func (h *Handler) TypedError(w http.ResponseWriter, r *http.Request) (e error) { func (h *Handler) TypedError(w http.ResponseWriter, r *http.Request) (e error) {
return ErrTyped return ErrTyped
} }

View File

@ -1,5 +1,9 @@
package main package main
// func () error
// func () error => func () *Error => decode => func() error
import ( import (
"context" "context"
"fmt" "fmt"
@ -89,6 +93,18 @@ func call() {
} }
} }
{
fmt.Println("-------------------------")
strct, err := c.Struct(ctx)
if err != nil {
panic("client error should be nil")
} else if strct == nil {
panic("service error should not be nil")
} else if strct != nil {
fmt.Println("OK")
}
}
{ {
fmt.Println("-------------------------") fmt.Println("-------------------------")
var gotsrpcErr *gotsrpc.Error var gotsrpcErr *gotsrpc.Error

View File

@ -17,6 +17,7 @@ const (
ServiceGoTSRPCProxyMultiScalar = "MultiScalar" ServiceGoTSRPCProxyMultiScalar = "MultiScalar"
ServiceGoTSRPCProxyScalar = "Scalar" ServiceGoTSRPCProxyScalar = "Scalar"
ServiceGoTSRPCProxyScalarError = "ScalarError" ServiceGoTSRPCProxyScalarError = "ScalarError"
ServiceGoTSRPCProxyStruct = "Struct"
ServiceGoTSRPCProxyTypedCustomError = "TypedCustomError" ServiceGoTSRPCProxyTypedCustomError = "TypedCustomError"
ServiceGoTSRPCProxyTypedError = "TypedError" ServiceGoTSRPCProxyTypedError = "TypedError"
ServiceGoTSRPCProxyTypedScalarError = "TypedScalarError" ServiceGoTSRPCProxyTypedScalarError = "TypedScalarError"
@ -146,6 +147,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 ServiceGoTSRPCProxyStruct:
var (
args []interface{}
rets []interface{}
)
executionStart := time.Now()
rw := gotsrpc.ResponseWriter{ResponseWriter: w}
structE := p.service.Struct(&rw, r)
callStats.Execution = time.Since(executionStart)
if rw.Status() == http.StatusOK {
rets = []interface{}{structE}
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{}

View File

@ -16,6 +16,7 @@ type ServiceGoTSRPCClient interface {
MultiScalar(ctx go_context.Context) (e *MultiScalar, clientErr error) MultiScalar(ctx go_context.Context) (e *MultiScalar, clientErr error)
Scalar(ctx go_context.Context) (e *Scalar, clientErr error) Scalar(ctx go_context.Context) (e *Scalar, 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 *Struct, 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)
@ -94,6 +95,16 @@ func (tsc *HTTPServiceGoTSRPCClient) ScalarError(ctx go_context.Context) (e erro
return return
} }
func (tsc *HTTPServiceGoTSRPCClient) Struct(ctx go_context.Context) (e *Struct, clientErr error) {
args := []interface{}{}
reply := []interface{}{&e}
clientErr = tsc.Client.Call(ctx, tsc.URL, tsc.EndPoint, "Struct", args, reply)
if clientErr != nil {
clientErr = pkg_errors.WithMessage(clientErr, "failed to call backend.ServiceGoTSRPCProxy Struct")
}
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}

View File

@ -12,6 +12,23 @@ const (
type Scalar string type Scalar string
func (s Scalar) String() string {
return string(s)
}
func (s *Scalar) Error() string {
return s.String()
}
type Struct struct {
Message string `json:"message"`
Data string `json:"data"`
}
func (s *Struct) Error() string {
return s.Message
}
type ( type (
ScalarA string ScalarA string
ScalarB string ScalarB string
@ -36,6 +53,7 @@ type Service interface {
Error(w http.ResponseWriter, r *http.Request) (e error) Error(w http.ResponseWriter, r *http.Request) (e error)
Scalar(w http.ResponseWriter, r *http.Request) (e *Scalar) Scalar(w http.ResponseWriter, r *http.Request) (e *Scalar)
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 *Struct)
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)

View File

@ -4,8 +4,9 @@ import (
"net/http" "net/http"
"reflect" "reflect"
"time" "time"
"unsafe"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"github.com/ugorji/go/codec" "github.com/ugorji/go/codec"
) )
@ -53,22 +54,12 @@ var msgpackClientHandle = &clientHandle{
return ret, nil return ret, nil
}, },
afterDecodeReply: func(reply *[]interface{}, wrappedReply []interface{}) error { afterDecodeReply: func(reply *[]interface{}, wrappedReply []interface{}) error {
ptr := func(v reflect.Value) reflect.Value {
pt := reflect.PtrTo(v.Type()) // create a *T type.
pv := reflect.New(pt.Elem()) // create a reflect.Value of type *T.
pv.Elem().Set(v) // sets pv to point to underlying value of v.
return pv
}
for k, v := range wrappedReply { for k, v := range wrappedReply {
if e, ok := v.(*Error); ok && e != nil { if e, ok := v.(*Error); ok && e != nil {
if y, ok := (*reply)[k].(*error); ok { if y, ok := (*reply)[k].(*error); ok {
*y = e *y = e
} else { } else if err := mapstructure.Decode(e.Data, (*reply)[k]); err != nil {
rv := reflect.ValueOf((*reply)[k]).Elem() return errors.Wrap(err, "failed to decode wrapped error")
elem := reflect.NewAt(rv.Type().Elem(), unsafe.Pointer(rv.UnsafeAddr())).Elem()
elem.Set(reflect.ValueOf(e.Data).Convert(elem.Type()))
rv.Set(ptr(elem))
} }
} }
} }