mirror of
https://github.com/tendermint/tendermint.git
synced 2026-06-01 11:56:21 +00:00
We should not set cache-control headers on RPC responses. HTTP caching interacts poorly with resources that are expected to change frequently, or whose rate of change is unpredictable. More subtly, all calls to the POST endpoint use the same URL, which means a cacheable response from one call may actually "hide" an uncacheable response from a subsequent one. This is less of a problem for the GET endpoints, but that means the behaviour of RPCs varies depending on which HTTP method your client happens to use. Websocket requests were already marked statically uncacheable, adding yet a third combination. To address this: - Stop setting cache-control headers. - Update the tests that were checking for those headers. - Remove the flags to request cache-control. Apart from affecting the HTTP response headers, this change does not modify the behaviour of any of the RPC methods.
98 lines
2.7 KiB
Go
98 lines
2.7 KiB
Go
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
|
|
}
|
|
|
|
// NewRPCFunc wraps a function for introspection.
|
|
// f is the function, args are comma separated argument names
|
|
func NewRPCFunc(f interface{}, args string) *RPCFunc {
|
|
return newRPCFunc(f, args, false)
|
|
}
|
|
|
|
// NewWSRPCFunc wraps a function for introspection and use in the websockets.
|
|
func NewWSRPCFunc(f interface{}, args string) *RPCFunc {
|
|
return newRPCFunc(f, args, true)
|
|
}
|
|
|
|
func newRPCFunc(f interface{}, args string, ws 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,
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|