From 6f6935a44b8cc93ad86dc4bd64b396f80e89a1d1 Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Thu, 27 Jan 2022 14:52:41 -0800 Subject: [PATCH] rpc: don't route websocket-only methods on GET requests (#7715) --- rpc/jsonrpc/server/http_uri_handler.go | 26 +++++++------------------- rpc/jsonrpc/server/rpc_func.go | 16 ++++++++-------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/rpc/jsonrpc/server/http_uri_handler.go b/rpc/jsonrpc/server/http_uri_handler.go index 0728b1f08..573631a38 100644 --- a/rpc/jsonrpc/server/http_uri_handler.go +++ b/rpc/jsonrpc/server/http_uri_handler.go @@ -16,24 +16,12 @@ import ( rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) -// HTTP + URI handler +// uriReqID is a placeholder ID used for GET requests, which do not receive a +// JSON-RPC request ID from the caller. +var uriReqID = rpctypes.JSONRPCIntID(-1) // convert from a function name to the http handler func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWriter, *http.Request) { - // Always return -1 as there's no ID here. - dummyID := rpctypes.JSONRPCIntID(-1) // URIClientRequestID - - // Exception for websocket endpoints - // - // TODO(creachadair): Rather than reporting errors for these, we should - // remove them from the routing list entirely on this endpoint. - if rpcFunc.ws { - return func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - } - } - - // All other endpoints return func(w http.ResponseWriter, req *http.Request) { ctx := rpctypes.WithCallInfo(req.Context(), &rpctypes.CallInfo{ HTTPRequest: req, @@ -52,11 +40,11 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit switch e := err.(type) { // if no error then return a success response case nil: - writeHTTPResponse(w, logger, rpctypes.NewRPCSuccessResponse(dummyID, result)) + writeHTTPResponse(w, logger, rpctypes.NewRPCSuccessResponse(uriReqID, result)) // if this already of type RPC error then forward that error. case *rpctypes.RPCError: - writeHTTPResponse(w, logger, rpctypes.NewRPCErrorResponse(dummyID, e.Code, e.Message, e.Data)) + writeHTTPResponse(w, logger, rpctypes.NewRPCErrorResponse(uriReqID, e.Code, e.Message, e.Data)) default: // we need to unwrap the error and parse it accordingly switch errors.Unwrap(err) { @@ -64,9 +52,9 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit coretypes.ErrZeroOrNegativePerPage, coretypes.ErrPageOutOfRange, coretypes.ErrInvalidRequest: - writeHTTPResponse(w, logger, rpctypes.RPCInvalidRequestError(dummyID, err)) + writeHTTPResponse(w, logger, rpctypes.RPCInvalidRequestError(uriReqID, err)) default: // ctypes.ErrHeightNotAvailable, ctypes.ErrHeightExceedsChainHead: - writeHTTPResponse(w, logger, rpctypes.RPCInternalError(dummyID, err)) + writeHTTPResponse(w, logger, rpctypes.RPCInternalError(uriReqID, err)) } } } diff --git a/rpc/jsonrpc/server/rpc_func.go b/rpc/jsonrpc/server/rpc_func.go index 4ccd045b9..a58973c6e 100644 --- a/rpc/jsonrpc/server/rpc_func.go +++ b/rpc/jsonrpc/server/rpc_func.go @@ -10,17 +10,17 @@ import ( "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 +// RegisterRPCFuncs adds a route to mux for each non-websocket function in the +// funcMap, and also a root JSON-RPC POST handler. 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)) + for name, fn := range funcMap { + if fn.ws { + continue // skip websocket endpoints, not usable via GET calls + } + mux.HandleFunc("/"+name, makeHTTPHandler(fn, logger)) } - // JSONRPC endpoints + // Endpoints for POST. mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger))) }