- package server
-
- import (
- "net/http"
- "reflect"
- "strings"
-
- "github.com/tendermint/tendermint/libs/log"
- )
-
- // RegisterRPCFuncs adds a route for each function in the funcMap, as well as
- // general jsonrpc and websocket handlers for all functions. "result" is the
- // interface on which the result objects are registered, and is popualted with
- // every RPCResponse
- func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, logger log.Logger) {
- // HTTP endpoints
- for funcName, rpcFunc := range funcMap {
- mux.HandleFunc("/"+funcName, makeHTTPHandler(rpcFunc, logger))
- }
-
- // JSONRPC endpoints
- mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger)))
- }
-
- // Function introspection
-
- // RPCFunc contains the introspected type information for a function
- type RPCFunc struct {
- f reflect.Value // underlying rpc function
- args []reflect.Type // type of each function arg
- returns []reflect.Type // type of each return arg
- argNames []string // name of each argument
- ws bool // websocket only
- cache bool // allow the RPC response can be cached by the proxy cache server
- }
-
- // NewRPCFunc wraps a function for introspection.
- // f is the function, args are comma separated argument names
- // cache is a bool value to allow the client proxy server to cache the RPC results
- func NewRPCFunc(f interface{}, args string, cache bool) *RPCFunc {
- return newRPCFunc(f, args, false, cache)
- }
-
- // NewWSRPCFunc wraps a function for introspection and use in the websockets.
- func NewWSRPCFunc(f interface{}, args string) *RPCFunc {
- return newRPCFunc(f, args, true, false)
- }
-
- func newRPCFunc(f interface{}, args string, ws bool, c bool) *RPCFunc {
- var argNames []string
- if args != "" {
- argNames = strings.Split(args, ",")
- }
- return &RPCFunc{
- f: reflect.ValueOf(f),
- args: funcArgTypes(f),
- returns: funcReturnTypes(f),
- argNames: argNames,
- ws: ws,
- cache: c,
- }
- }
-
- // return a function's argument types
- func funcArgTypes(f interface{}) []reflect.Type {
- t := reflect.TypeOf(f)
- n := t.NumIn()
- typez := make([]reflect.Type, n)
- for i := 0; i < n; i++ {
- typez[i] = t.In(i)
- }
- return typez
- }
-
- // return a function's return types
- func funcReturnTypes(f interface{}) []reflect.Type {
- t := reflect.TypeOf(f)
- n := t.NumOut()
- typez := make([]reflect.Type, n)
- for i := 0; i < n; i++ {
- typez[i] = t.Out(i)
- }
- return typez
- }
-
- //-------------------------------------------------------------
-
- // NOTE: assume returns is result struct and error. If error is not nil, return it
- func unreflectResult(returns []reflect.Value) (interface{}, error) {
- errV := returns[1]
- if err, ok := errV.Interface().(error); ok && err != nil {
- return nil, err
- }
- rv := returns[0]
- // the result is a registered interface,
- // we need a pointer to it so we can marshal with type byte
- rvp := reflect.New(rv.Type())
- rvp.Elem().Set(rv)
- return rvp.Interface(), nil
- }
|