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