From 9851265d4f26cadc251b5865a622058894aa1d89 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 25 Apr 2017 23:09:47 -0400 Subject: [PATCH] rpc: use HTTP error codes --- rpc/server/handlers.go | 20 ++++++++++---------- rpc/server/http_server.go | 11 +++++++++++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/rpc/server/handlers.go b/rpc/server/handlers.go index f5b3659d3..a0dbc487a 100644 --- a/rpc/server/handlers.go +++ b/rpc/server/handlers.go @@ -14,8 +14,8 @@ import ( "github.com/gorilla/websocket" "github.com/pkg/errors" - types "github.com/tendermint/tendermint/rpc/types" wire "github.com/tendermint/go-wire" + types "github.com/tendermint/tendermint/rpc/types" cmn "github.com/tendermint/tmlibs/common" events "github.com/tendermint/tmlibs/events" ) @@ -108,32 +108,32 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc { var request types.RPCRequest err := json.Unmarshal(b, &request) if err != nil { - WriteRPCResponseHTTP(w, types.NewRPCResponse("", nil, fmt.Sprintf("Error unmarshalling request: %v", err.Error()))) + WriteRPCResponseHTTPError(w, http.StatusBadRequest, types.NewRPCResponse("", nil, fmt.Sprintf("Error unmarshalling request: %v", err.Error()))) return } if len(r.URL.Path) > 1 { - WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, nil, fmt.Sprintf("Invalid JSONRPC endpoint %s", r.URL.Path))) + WriteRPCResponseHTTPError(w, http.StatusNotFound, types.NewRPCResponse(request.ID, nil, fmt.Sprintf("Invalid JSONRPC endpoint %s", r.URL.Path))) return } rpcFunc := funcMap[request.Method] if rpcFunc == nil { - WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, nil, "RPC method unknown: "+request.Method)) + WriteRPCResponseHTTPError(w, http.StatusNotFound, types.NewRPCResponse(request.ID, nil, "RPC method unknown: "+request.Method)) return } if rpcFunc.ws { - WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, nil, "RPC method is only for websockets: "+request.Method)) + WriteRPCResponseHTTPError(w, http.StatusMethodNotAllowed, types.NewRPCResponse(request.ID, nil, "RPC method is only for websockets: "+request.Method)) return } args, err := jsonParamsToArgsRPC(rpcFunc, request.Params) if err != nil { - WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, nil, fmt.Sprintf("Error converting json params to arguments: %v", err.Error()))) + WriteRPCResponseHTTPError(w, http.StatusBadRequest, types.NewRPCResponse(request.ID, nil, fmt.Sprintf("Error converting json params to arguments: %v", err.Error()))) return } returns := rpcFunc.f.Call(args) log.Info("HTTPJSONRPC", "method", request.Method, "args", args, "returns", returns) result, err := unreflectResult(returns) if err != nil { - WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, result, err.Error())) + WriteRPCResponseHTTPError(w, http.StatusInternalServerError, types.NewRPCResponse(request.ID, result, err.Error())) return } WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, result, "")) @@ -221,7 +221,7 @@ func makeHTTPHandler(rpcFunc *RPCFunc) func(http.ResponseWriter, *http.Request) // Exception for websocket endpoints if rpcFunc.ws { return func(w http.ResponseWriter, r *http.Request) { - WriteRPCResponseHTTP(w, types.NewRPCResponse("", nil, "This RPC method is only for websockets")) + WriteRPCResponseHTTPError(w, http.StatusMethodNotAllowed, types.NewRPCResponse("", nil, "This RPC method is only for websockets")) } } // All other endpoints @@ -229,14 +229,14 @@ func makeHTTPHandler(rpcFunc *RPCFunc) func(http.ResponseWriter, *http.Request) log.Debug("HTTP HANDLER", "req", r) args, err := httpParamsToArgs(rpcFunc, r) if err != nil { - WriteRPCResponseHTTP(w, types.NewRPCResponse("", nil, fmt.Sprintf("Error converting http params to args: %v", err.Error()))) + WriteRPCResponseHTTPError(w, http.StatusBadRequest, types.NewRPCResponse("", nil, fmt.Sprintf("Error converting http params to args: %v", err.Error()))) return } returns := rpcFunc.f.Call(args) log.Info("HTTPRestRPC", "method", r.URL.Path, "args", args, "returns", returns) result, err := unreflectResult(returns) if err != nil { - WriteRPCResponseHTTP(w, types.NewRPCResponse("", nil, err.Error())) + WriteRPCResponseHTTPError(w, http.StatusInternalServerError, types.NewRPCResponse("", nil, err.Error())) return } WriteRPCResponseHTTP(w, types.NewRPCResponse("", result, "")) diff --git a/rpc/server/http_server.go b/rpc/server/http_server.go index a613be253..b30bc3606 100644 --- a/rpc/server/http_server.go +++ b/rpc/server/http_server.go @@ -46,6 +46,17 @@ func StartHTTPServer(listenAddr string, handler http.Handler) (listener net.List return listener, nil } +func WriteRPCResponseHTTPError(w http.ResponseWriter, httpCode int, res types.RPCResponse) { + jsonBytes, err := json.Marshal(res) + if err != nil { + panic(err) + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpCode) + w.Write(jsonBytes) +} + func WriteRPCResponseHTTP(w http.ResponseWriter, res types.RPCResponse) { // jsonBytes := wire.JSONBytesPretty(res) jsonBytes, err := json.Marshal(res)