include optional data field in error object
``` data A Primitive or Structured value that contains additional information about the error. This may be omitted. The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.). ```
This commit is contained in:
parent
6c1572c9b8
commit
f74de4cb86
|
@ -110,11 +110,11 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger log.Logger) http.Han
|
|||
var request types.RPCRequest
|
||||
err := json.Unmarshal(b, &request)
|
||||
if err != nil {
|
||||
WriteRPCResponseHTTP(w, types.RPCParseError(""))
|
||||
WriteRPCResponseHTTP(w, types.RPCParseError("", errors.Wrap(err, "Error unmarshalling request")))
|
||||
return
|
||||
}
|
||||
if len(r.URL.Path) > 1 {
|
||||
WriteRPCResponseHTTP(w, types.RPCInvalidRequestError(request.ID))
|
||||
WriteRPCResponseHTTP(w, types.RPCInvalidRequestError(request.ID, errors.Errorf("Path %s is invalid", r.URL.Path)))
|
||||
return
|
||||
}
|
||||
rpcFunc := funcMap[request.Method]
|
||||
|
@ -123,19 +123,19 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger log.Logger) http.Han
|
|||
return
|
||||
}
|
||||
if rpcFunc.ws {
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError(request.ID))
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError(request.ID, errors.New("Trying to use Websocket method in non-ws context")))
|
||||
return
|
||||
}
|
||||
args, err := jsonParamsToArgsRPC(rpcFunc, request.Params)
|
||||
if err != nil {
|
||||
WriteRPCResponseHTTP(w, types.RPCInvalidParamsError(request.ID))
|
||||
WriteRPCResponseHTTP(w, types.RPCInvalidParamsError(request.ID, errors.Wrap(err, "Error converting json params to arguments")))
|
||||
return
|
||||
}
|
||||
returns := rpcFunc.f.Call(args)
|
||||
logger.Info("HTTPJSONRPC", "method", request.Method, "args", args, "returns", returns)
|
||||
result, err := unreflectResult(returns)
|
||||
if err != nil {
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError(request.ID))
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError(request.ID, err))
|
||||
return
|
||||
}
|
||||
WriteRPCResponseHTTP(w, types.NewRPCSuccessResponse(request.ID, result))
|
||||
|
@ -229,7 +229,7 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit
|
|||
// Exception for websocket endpoints
|
||||
if rpcFunc.ws {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError(""))
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError("", errors.New("Trying to use Websocket method in non-ws context")))
|
||||
}
|
||||
}
|
||||
// All other endpoints
|
||||
|
@ -237,14 +237,14 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit
|
|||
logger.Debug("HTTP HANDLER", "req", r)
|
||||
args, err := httpParamsToArgs(rpcFunc, r)
|
||||
if err != nil {
|
||||
WriteRPCResponseHTTP(w, types.RPCInvalidParamsError(""))
|
||||
WriteRPCResponseHTTP(w, types.RPCInvalidParamsError("", errors.Wrap(err, "Error converting http params to arguments")))
|
||||
return
|
||||
}
|
||||
returns := rpcFunc.f.Call(args)
|
||||
logger.Info("HTTPRestRPC", "method", r.URL.Path, "args", args, "returns", returns)
|
||||
result, err := unreflectResult(returns)
|
||||
if err != nil {
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError(""))
|
||||
WriteRPCResponseHTTP(w, types.RPCInternalError("", err))
|
||||
return
|
||||
}
|
||||
WriteRPCResponseHTTP(w, types.NewRPCSuccessResponse("", result))
|
||||
|
@ -509,7 +509,7 @@ func (wsc *wsConnection) readRoutine() {
|
|||
var request types.RPCRequest
|
||||
err = json.Unmarshal(in, &request)
|
||||
if err != nil {
|
||||
wsc.WriteRPCResponse(types.RPCParseError(""))
|
||||
wsc.WriteRPCResponse(types.RPCParseError("", errors.Wrap(err, "Error unmarshaling request")))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -528,7 +528,7 @@ func (wsc *wsConnection) readRoutine() {
|
|||
args, err = jsonParamsToArgsRPC(rpcFunc, request.Params)
|
||||
}
|
||||
if err != nil {
|
||||
wsc.WriteRPCResponse(types.RPCInternalError(request.ID))
|
||||
wsc.WriteRPCResponse(types.RPCInternalError(request.ID, errors.Wrap(err, "Error converting json params to arguments")))
|
||||
continue
|
||||
}
|
||||
returns := rpcFunc.f.Call(args)
|
||||
|
@ -538,7 +538,7 @@ func (wsc *wsConnection) readRoutine() {
|
|||
|
||||
result, err := unreflectResult(returns)
|
||||
if err != nil {
|
||||
wsc.WriteRPCResponse(types.RPCInternalError(request.ID))
|
||||
wsc.WriteRPCResponse(types.RPCInternalError(request.ID, err))
|
||||
continue
|
||||
} else {
|
||||
wsc.WriteRPCResponse(types.NewRPCSuccessResponse(request.ID, result))
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
types "github.com/tendermint/tendermint/rpc/lib/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
)
|
||||
|
@ -99,7 +100,7 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler
|
|||
// For the rest,
|
||||
logger.Error("Panic in RPC HTTP handler", "err", e, "stack", string(debug.Stack()))
|
||||
rww.WriteHeader(http.StatusInternalServerError)
|
||||
WriteRPCResponseHTTP(rww, types.RPCInternalError(""))
|
||||
WriteRPCResponseHTTP(rww, types.RPCInternalError("", e.(error)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
events "github.com/tendermint/tmlibs/events"
|
||||
)
|
||||
|
||||
type RpcError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
//----------------------------------------
|
||||
// REQUEST
|
||||
|
||||
type RPCRequest struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
|
@ -52,6 +52,13 @@ func ArrayToRequest(id string, method string, params []interface{}) (RPCRequest,
|
|||
}
|
||||
|
||||
//----------------------------------------
|
||||
// RESPONSE
|
||||
|
||||
type RpcError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data string `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type RPCResponse struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
|
@ -67,7 +74,7 @@ func NewRPCSuccessResponse(id string, res interface{}) RPCResponse {
|
|||
var js []byte
|
||||
js, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
return RPCInternalError(id)
|
||||
return RPCInternalError(id, errors.Wrap(err, "Error marshalling response"))
|
||||
}
|
||||
rawMsg := json.RawMessage(js)
|
||||
raw = &rawMsg
|
||||
|
@ -76,11 +83,11 @@ func NewRPCSuccessResponse(id string, res interface{}) RPCResponse {
|
|||
return RPCResponse{JSONRPC: "2.0", ID: id, Result: raw}
|
||||
}
|
||||
|
||||
func NewRPCErrorResponse(id string, code int, msg string) RPCResponse {
|
||||
func NewRPCErrorResponse(id string, code int, msg string, data string) RPCResponse {
|
||||
return RPCResponse{
|
||||
JSONRPC: "2.0",
|
||||
ID: id,
|
||||
Error: &RpcError{Code: code, Message: msg},
|
||||
Error: &RpcError{Code: code, Message: msg, Data: data},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,28 +99,28 @@ func (resp RPCResponse) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
func RPCParseError(id string) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32700, "Parse error. Invalid JSON")
|
||||
func RPCParseError(id string, err error) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32700, "Parse error. Invalid JSON", err.Error())
|
||||
}
|
||||
|
||||
func RPCInvalidRequestError(id string) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32600, "Invalid Request")
|
||||
func RPCInvalidRequestError(id string, err error) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32600, "Invalid Request", err.Error())
|
||||
}
|
||||
|
||||
func RPCMethodNotFoundError(id string) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32601, "Method not found")
|
||||
return NewRPCErrorResponse(id, -32601, "Method not found", "")
|
||||
}
|
||||
|
||||
func RPCInvalidParamsError(id string) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32602, "Invalid params")
|
||||
func RPCInvalidParamsError(id string, err error) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32602, "Invalid params", err.Error())
|
||||
}
|
||||
|
||||
func RPCInternalError(id string) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32603, "Internal error")
|
||||
func RPCInternalError(id string, err error) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32603, "Internal error", err.Error())
|
||||
}
|
||||
|
||||
func RPCServerError(id string) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32000, "Server error")
|
||||
func RPCServerError(id string, err error) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32000, "Server error", err.Error())
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
@ -133,7 +140,7 @@ type WSRPCContext struct {
|
|||
}
|
||||
|
||||
//----------------------------------------
|
||||
// sockets
|
||||
// SOCKETS
|
||||
//
|
||||
// Determine if its a unix or tcp socket.
|
||||
// If tcp, must specify the port; `0.0.0.0` will return incorrectly as "unix" since there's no port
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -19,14 +20,13 @@ func TestResponses(t *testing.T) {
|
|||
s := `{"jsonrpc":"2.0","id":"1","result":{"Value":"hello"}}`
|
||||
assert.Equal(string(s), string(b))
|
||||
|
||||
d := RPCParseError("1")
|
||||
d := RPCParseError("1", errors.New("Hello world"))
|
||||
e, _ := json.Marshal(d)
|
||||
f := `{"jsonrpc":"2.0","id":"1","error":{"code":-32700,"message":"Parse error. Invalid JSON"}}`
|
||||
f := `{"jsonrpc":"2.0","id":"1","error":{"code":-32700,"message":"Parse error. Invalid JSON","data":"Hello world"}}`
|
||||
assert.Equal(string(f), string(e))
|
||||
|
||||
g := RPCMethodNotFoundError("2")
|
||||
h, _ := json.Marshal(g)
|
||||
i := `{"jsonrpc":"2.0","id":"2","error":{"code":-32601,"message":"Method not found"}}`
|
||||
assert.Equal(string(h), string(i))
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue