github.com/okex/exchain@v1.8.0/libs/tendermint/rpc/jsonrpc/server/rpc_func.go (about) 1 package server 2 3 import ( 4 "net/http" 5 "reflect" 6 "strings" 7 8 "github.com/pkg/errors" 9 10 amino "github.com/tendermint/go-amino" 11 12 "github.com/okex/exchain/libs/tendermint/libs/log" 13 ) 14 15 // RegisterRPCFuncs adds a route for each function in the funcMap, as well as 16 // general jsonrpc and websocket handlers for all functions. "result" is the 17 // interface on which the result objects are registered, and is popualted with 18 // every RPCResponse 19 func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, cdc *amino.Codec, logger log.Logger) { 20 // HTTP endpoints 21 for funcName, rpcFunc := range funcMap { 22 mux.HandleFunc("/"+funcName, makeHTTPHandler(rpcFunc, cdc, logger)) 23 } 24 25 // JSONRPC endpoints 26 mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, cdc, logger))) 27 } 28 29 /////////////////////////////////////////////////////////////////////////////// 30 // Function introspection 31 /////////////////////////////////////////////////////////////////////////////// 32 33 // RPCFunc contains the introspected type information for a function 34 type RPCFunc struct { 35 f reflect.Value // underlying rpc function 36 args []reflect.Type // type of each function arg 37 returns []reflect.Type // type of each return arg 38 argNames []string // name of each argument 39 ws bool // websocket only 40 } 41 42 // NewRPCFunc wraps a function for introspection. 43 // f is the function, args are comma separated argument names 44 func NewRPCFunc(f interface{}, args string) *RPCFunc { 45 return newRPCFunc(f, args, false) 46 } 47 48 // NewWSRPCFunc wraps a function for introspection and use in the websockets. 49 func NewWSRPCFunc(f interface{}, args string) *RPCFunc { 50 return newRPCFunc(f, args, true) 51 } 52 53 func newRPCFunc(f interface{}, args string, ws bool) *RPCFunc { 54 var argNames []string 55 if args != "" { 56 argNames = strings.Split(args, ",") 57 } 58 return &RPCFunc{ 59 f: reflect.ValueOf(f), 60 args: funcArgTypes(f), 61 returns: funcReturnTypes(f), 62 argNames: argNames, 63 ws: ws, 64 } 65 } 66 67 // return a function's argument types 68 func funcArgTypes(f interface{}) []reflect.Type { 69 t := reflect.TypeOf(f) 70 n := t.NumIn() 71 typez := make([]reflect.Type, n) 72 for i := 0; i < n; i++ { 73 typez[i] = t.In(i) 74 } 75 return typez 76 } 77 78 // return a function's return types 79 func funcReturnTypes(f interface{}) []reflect.Type { 80 t := reflect.TypeOf(f) 81 n := t.NumOut() 82 typez := make([]reflect.Type, n) 83 for i := 0; i < n; i++ { 84 typez[i] = t.Out(i) 85 } 86 return typez 87 } 88 89 //------------------------------------------------------------- 90 91 // NOTE: assume returns is result struct and error. If error is not nil, return it 92 func unreflectResult(returns []reflect.Value) (interface{}, error) { 93 errV := returns[1] 94 if errV.Interface() != nil { 95 return nil, errors.Errorf("%v", errV.Interface()) 96 } 97 rv := returns[0] 98 // the result is a registered interface, 99 // we need a pointer to it so we can marshal with type byte 100 rvp := reflect.New(rv.Type()) 101 rvp.Elem().Set(rv) 102 return rvp.Interface(), nil 103 }