Browse Source

rpc: don't route websocket-only methods on GET requests (#7715)

pull/7721/head
M. J. Fromberger 3 years ago
committed by GitHub
parent
commit
6f6935a44b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 27 deletions
  1. +7
    -19
      rpc/jsonrpc/server/http_uri_handler.go
  2. +8
    -8
      rpc/jsonrpc/server/rpc_func.go

+ 7
- 19
rpc/jsonrpc/server/http_uri_handler.go View File

@ -16,24 +16,12 @@ import (
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" 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 // convert from a function name to the http handler
func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWriter, *http.Request) { 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) { return func(w http.ResponseWriter, req *http.Request) {
ctx := rpctypes.WithCallInfo(req.Context(), &rpctypes.CallInfo{ ctx := rpctypes.WithCallInfo(req.Context(), &rpctypes.CallInfo{
HTTPRequest: req, HTTPRequest: req,
@ -52,11 +40,11 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit
switch e := err.(type) { switch e := err.(type) {
// if no error then return a success response // if no error then return a success response
case nil: 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. // if this already of type RPC error then forward that error.
case *rpctypes.RPCError: 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 default: // we need to unwrap the error and parse it accordingly
switch errors.Unwrap(err) { switch errors.Unwrap(err) {
@ -64,9 +52,9 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit
coretypes.ErrZeroOrNegativePerPage, coretypes.ErrZeroOrNegativePerPage,
coretypes.ErrPageOutOfRange, coretypes.ErrPageOutOfRange,
coretypes.ErrInvalidRequest: coretypes.ErrInvalidRequest:
writeHTTPResponse(w, logger, rpctypes.RPCInvalidRequestError(dummyID, err))
writeHTTPResponse(w, logger, rpctypes.RPCInvalidRequestError(uriReqID, err))
default: // ctypes.ErrHeightNotAvailable, ctypes.ErrHeightExceedsChainHead: default: // ctypes.ErrHeightNotAvailable, ctypes.ErrHeightExceedsChainHead:
writeHTTPResponse(w, logger, rpctypes.RPCInternalError(dummyID, err))
writeHTTPResponse(w, logger, rpctypes.RPCInternalError(uriReqID, err))
} }
} }
} }


+ 8
- 8
rpc/jsonrpc/server/rpc_func.go View File

@ -10,17 +10,17 @@ import (
"github.com/tendermint/tendermint/libs/log" "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) { 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))) mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger)))
} }


Loading…
Cancel
Save