mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-05-01 07:35:58 +08:00
errcode
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"Open_IM/pkg/common/constant"
|
||||
"Open_IM/pkg/common/log"
|
||||
"Open_IM/pkg/common/tracelog"
|
||||
utils2 "Open_IM/pkg/utils"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"google.golang.org/grpc/status"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ApiToRpc(c *gin.Context, apiReq, apiResp interface{}, rpcName string, rpcClientFunc interface{}, rpcFuncName string) {
|
||||
if rpcName == "" {
|
||||
rpcName = utils2.GetFuncName(1)
|
||||
}
|
||||
logFuncName := fmt.Sprintf("[ApiToRpc: %s]%s", utils2.GetFuncName(1), rpcFuncName)
|
||||
ctx := tracelog.NewCtx(c, rpcFuncName)
|
||||
defer log.ShowLog(ctx)
|
||||
if err := c.BindJSON(apiReq); err != nil {
|
||||
WriteErrorResponse(ctx, "BindJSON", err)
|
||||
return
|
||||
}
|
||||
tracelog.SetCtxInfo(ctx, logFuncName, nil, "apiReq", apiReq)
|
||||
etcdConn, err := rpc.GetConn(ctx, rpcName)
|
||||
if err != nil {
|
||||
WriteErrorResponse(ctx, "GetConn", err)
|
||||
return
|
||||
}
|
||||
rpcClient := reflect.ValueOf(rpcClientFunc).Call([]reflect.Value{
|
||||
reflect.ValueOf(etcdConn),
|
||||
})[0].MethodByName(rpcFuncName) // rpcClient func
|
||||
rpcReqPtr := reflect.New(rpcClient.Type().In(1).Elem()) // *req
|
||||
CopyAny(apiReq, rpcReqPtr.Interface())
|
||||
tracelog.SetCtxInfo(ctx, logFuncName, nil, "opUserID", c.GetString("opUserID"), "callRpcReq", rpcString(rpcReqPtr.Elem().Interface()))
|
||||
respArr := rpcClient.Call([]reflect.Value{
|
||||
reflect.ValueOf(context.Context(c)), // context.Context (ctx operationID. opUserID)
|
||||
rpcReqPtr, // rpcClient apiReq
|
||||
}) // respArr => (apiResp, error)
|
||||
if !respArr[1].IsNil() { // rpcClient err != nil
|
||||
err := respArr[1].Interface().(error)
|
||||
WriteErrorResponse(ctx, rpcFuncName, err, "callRpcResp", "error")
|
||||
return
|
||||
}
|
||||
rpcResp := respArr[0].Elem()
|
||||
tracelog.SetCtxInfo(ctx, rpcFuncName, nil, "callRpcResp", rpcString(rpcResp.Interface()))
|
||||
if apiResp != nil {
|
||||
CopyAny(rpcResp.Interface(), apiResp)
|
||||
}
|
||||
SetSuccess(ctx, rpcFuncName, apiResp)
|
||||
}
|
||||
|
||||
func rpcString(v interface{}) string {
|
||||
if s, ok := v.(interface{ String() string }); ok {
|
||||
return s.String()
|
||||
}
|
||||
return fmt.Sprintf("%+v", v)
|
||||
}
|
||||
|
||||
type baseResp struct {
|
||||
ErrCode int32 `json:"errCode"`
|
||||
ErrMsg string `json:"errMsg"`
|
||||
ErrDtl string `json:"errDtl"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func WriteErrorResponse(ctx context.Context, funcName string, err error, args ...interface{}) {
|
||||
tracelog.SetCtxInfo(ctx, funcName, err, args)
|
||||
e := tracelog.Unwrap(err)
|
||||
switch t := e.(type) {
|
||||
case *constant.ErrInfo:
|
||||
ctx.Value(tracelog.TraceLogKey).(*tracelog.ApiInfo).GinCtx.JSON(http.StatusOK, baseResp{ErrCode: t.ErrCode, ErrMsg: t.ErrMsg, ErrDtl: t.DetailErrMsg})
|
||||
//ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": t.ErrCode, "errMsg": t.ErrMsg, "errDtl": t.DetailErrMsg})
|
||||
return
|
||||
default:
|
||||
s, ok := status.FromError(e)
|
||||
if !ok {
|
||||
ctx.Value(tracelog.TraceLogKey).(*tracelog.ApiInfo).GinCtx.JSON(http.StatusOK, &baseResp{ErrCode: constant.ErrDefaultOther.ErrCode, ErrMsg: err.Error(), ErrDtl: fmt.Sprintf("%+v", err)})
|
||||
//ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": constant.ErrDefaultOther.ErrCode, "errMsg": err.Error(), "errDtl": fmt.Sprintf("%+v", err)})
|
||||
return
|
||||
}
|
||||
var details []string
|
||||
if err != e {
|
||||
details = append(details, fmt.Sprintf("%+v", err))
|
||||
}
|
||||
for _, s := range s.Details() {
|
||||
details = append(details, fmt.Sprintf("%+v", s))
|
||||
}
|
||||
ctx.Value(tracelog.TraceLogKey).(*tracelog.ApiInfo).GinCtx.JSON(http.StatusOK, &baseResp{ErrCode: int32(s.Code()), ErrMsg: s.Message(), ErrDtl: strings.Join(details, "\n")})
|
||||
//ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": s.Code(), "errMsg": s.Message(), "errDtl": strings.Join(details, "\n")})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func SetSuccess(ctx context.Context, funcName string, data interface{}) {
|
||||
tracelog.SetCtxInfo(ctx, funcName, nil, "data", data)
|
||||
ctx.Value(tracelog.TraceLogKey).(*tracelog.ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": 0, "errMsg": "", "errDtl": "", "data": data})
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func CopyAny(from, to interface{}) {
|
||||
copyAny(reflect.ValueOf(from), reflect.Indirect(reflect.ValueOf(to)))
|
||||
}
|
||||
|
||||
func copyAny(from, to reflect.Value) {
|
||||
if !to.CanSet() {
|
||||
return
|
||||
}
|
||||
if isBaseNil(from) {
|
||||
return
|
||||
}
|
||||
if isBaseNil(to) {
|
||||
to.Set(getBaseZeroValue(to.Type()))
|
||||
}
|
||||
btFrom := baseType(from.Type())
|
||||
btTo := baseType(to.Type())
|
||||
if btTo.Kind() == reflect.Interface || typeEq(btFrom, btTo) {
|
||||
setBaseValue(from, to)
|
||||
return
|
||||
}
|
||||
if _, ok := wrapType[btTo.String()]; ok { // string -> wrapperspb.StringValue
|
||||
val := reflect.New(btTo).Elem()
|
||||
copyAny(from, val.FieldByName("Value"))
|
||||
setBaseValue(val, to)
|
||||
return
|
||||
}
|
||||
if _, ok := wrapType[btFrom.String()]; ok { // wrapperspb.StringValue -> string
|
||||
copyAny(baseValue(from).FieldByName("Value"), to)
|
||||
return
|
||||
}
|
||||
if btFrom.Kind() == reflect.Struct && btTo.Kind() == reflect.Struct {
|
||||
copyStruct(baseValue(from), baseValue(to))
|
||||
return
|
||||
}
|
||||
if btFrom.Kind() == reflect.Slice && btTo.Kind() == reflect.Slice {
|
||||
copySlice(baseValue(from), baseValue(to))
|
||||
return
|
||||
}
|
||||
if btFrom.Kind() == reflect.Map && btTo.Kind() == reflect.Map {
|
||||
copyMap(baseValue(from), baseValue(to))
|
||||
return
|
||||
}
|
||||
if btTo.Kind() == reflect.String {
|
||||
if isBaseNil(to) {
|
||||
to.Set(getBaseZeroValue(baseType(to.Type())))
|
||||
}
|
||||
setBaseValue(reflect.ValueOf(toString(from)), to)
|
||||
return
|
||||
}
|
||||
if toNumber(from, to) {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func setBaseValue(from, to reflect.Value) {
|
||||
if isBaseNil(from) {
|
||||
return
|
||||
}
|
||||
var l int
|
||||
t := to.Type()
|
||||
for t.Kind() == reflect.Ptr {
|
||||
l++
|
||||
t = t.Elem()
|
||||
}
|
||||
v := baseValue(from)
|
||||
for i := 0; i < l; i++ {
|
||||
t := reflect.New(v.Type())
|
||||
t.Elem().Set(v)
|
||||
v = t
|
||||
}
|
||||
to.Set(v)
|
||||
}
|
||||
|
||||
func getBaseZeroValue(t reflect.Type) reflect.Value {
|
||||
var l int
|
||||
for t.Kind() == reflect.Ptr {
|
||||
l++
|
||||
t = t.Elem()
|
||||
}
|
||||
v := reflect.New(t)
|
||||
if l == 0 {
|
||||
v = v.Elem()
|
||||
} else {
|
||||
for i := 1; i < l; i++ {
|
||||
t := reflect.New(v.Type())
|
||||
t.Elem().Set(v)
|
||||
v = t
|
||||
}
|
||||
}
|
||||
r := reflect.New(v.Type()).Elem()
|
||||
r.Set(v)
|
||||
return r
|
||||
}
|
||||
|
||||
func isBaseNil(v reflect.Value) bool {
|
||||
for {
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr:
|
||||
v = v.Elem()
|
||||
case reflect.Invalid:
|
||||
return true
|
||||
default:
|
||||
return isNil(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func baseType(t reflect.Type) reflect.Type {
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func typeEq(t1, t2 reflect.Type) bool {
|
||||
return t1.String() == t2.String()
|
||||
}
|
||||
|
||||
func isNil(value reflect.Value) bool {
|
||||
switch value.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
|
||||
return value.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func baseValue(value reflect.Value) reflect.Value {
|
||||
for value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func copyStruct(from, to reflect.Value) {
|
||||
toType := to.Type()
|
||||
fromType := from.Type()
|
||||
n := to.NumField()
|
||||
for i := 0; i < n; i++ {
|
||||
toFieldType := toType.Field(i)
|
||||
if _, found := fromType.FieldByName(toFieldType.Name); !found {
|
||||
continue
|
||||
}
|
||||
copyAny(from.FieldByName(toFieldType.Name), to.Field(i))
|
||||
}
|
||||
}
|
||||
|
||||
func copySlice(from, to reflect.Value) {
|
||||
size := from.Len()
|
||||
temp := reflect.MakeSlice(to.Type(), 0, size)
|
||||
elemTo := to.Type().Elem()
|
||||
for i := 0; i < size; i++ {
|
||||
var itemTo reflect.Value
|
||||
if item := from.Index(i); isBaseNil(item) {
|
||||
itemTo = reflect.Zero(elemTo)
|
||||
} else {
|
||||
itemTo = getBaseZeroValue(elemTo)
|
||||
copyAny(from.Index(i), itemTo)
|
||||
}
|
||||
temp = reflect.Append(temp, itemTo)
|
||||
}
|
||||
to.Set(temp)
|
||||
}
|
||||
|
||||
func copyMap(from, to reflect.Value) {
|
||||
to.Set(reflect.MakeMap(to.Type()))
|
||||
toTypeKey := to.Type().Key()
|
||||
toTypeVal := to.Type().Elem()
|
||||
for r := from.MapRange(); r.Next(); {
|
||||
key := getBaseZeroValue(toTypeKey)
|
||||
copyAny(r.Key(), key)
|
||||
var val reflect.Value
|
||||
fVal := r.Value()
|
||||
if isBaseNil(fVal) {
|
||||
val = reflect.Zero(toTypeVal)
|
||||
} else {
|
||||
val = getBaseZeroValue(toTypeVal)
|
||||
copyAny(fVal, val)
|
||||
}
|
||||
to.SetMapIndex(key, val)
|
||||
}
|
||||
}
|
||||
|
||||
func toString(value reflect.Value) string {
|
||||
if value.Kind() == reflect.Slice {
|
||||
switch value.Type().String() {
|
||||
case "[]uint8": // []byte -> []uint8
|
||||
return string(value.Interface().([]uint8))
|
||||
case "[]int32": // []rune -> []int32
|
||||
return string(value.Interface().([]int32))
|
||||
}
|
||||
}
|
||||
return fmt.Sprint(value.Interface())
|
||||
}
|
||||
|
||||
func toNumber(from, to reflect.Value) bool {
|
||||
initTo := func() {
|
||||
if isBaseNil(to) {
|
||||
to.Set(getBaseZeroValue(to.Type()))
|
||||
}
|
||||
}
|
||||
switch baseValue(from).Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch baseValue(to).Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
initTo()
|
||||
baseValue(to).SetInt(baseValue(from).Int())
|
||||
return true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
initTo()
|
||||
baseValue(to).SetUint(uint64(baseValue(from).Int()))
|
||||
return true
|
||||
case reflect.Float64, reflect.Float32:
|
||||
initTo()
|
||||
baseValue(to).SetFloat(float64(baseValue(from).Int()))
|
||||
return true
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
switch baseValue(to).Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
initTo()
|
||||
baseValue(to).SetInt(int64(baseValue(from).Uint()))
|
||||
return true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
initTo()
|
||||
baseValue(to).SetInt(int64(baseValue(from).Uint()))
|
||||
return true
|
||||
case reflect.Float64, reflect.Float32:
|
||||
initTo()
|
||||
baseValue(to).SetFloat(float64(baseValue(from).Uint()))
|
||||
return true
|
||||
}
|
||||
case reflect.Float64, reflect.Float32:
|
||||
switch baseValue(to).Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
initTo()
|
||||
baseValue(to).SetInt(int64(baseValue(from).Float()))
|
||||
return true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
initTo()
|
||||
baseValue(to).SetUint(uint64(baseValue(from).Float()))
|
||||
return true
|
||||
case reflect.Float64, reflect.Float32:
|
||||
initTo()
|
||||
baseValue(to).SetFloat(baseValue(from).Float())
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func typeName(v interface{}) string {
|
||||
return reflect.TypeOf(v).String()
|
||||
}
|
||||
|
||||
var wrapType = map[string]struct{}{
|
||||
typeName(wrapperspb.DoubleValue{}): {},
|
||||
typeName(wrapperspb.FloatValue{}): {},
|
||||
typeName(wrapperspb.Int64Value{}): {},
|
||||
typeName(wrapperspb.UInt64Value{}): {},
|
||||
typeName(wrapperspb.Int32Value{}): {},
|
||||
typeName(wrapperspb.UInt32Value{}): {},
|
||||
typeName(wrapperspb.BoolValue{}): {},
|
||||
typeName(wrapperspb.StringValue{}): {},
|
||||
typeName(wrapperspb.BytesValue{}): {},
|
||||
}
|
||||
Reference in New Issue
Block a user