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