From 183c492b81034f0a2ec3746f6ca3df69c80c1dd7 Mon Sep 17 00:00:00 2001 From: Shane Jonas Date: Tue, 23 Sep 2025 10:29:46 -0400 Subject: [PATCH] fix: allow JSON-RPC error data in responses --- rpcserver/jsonrpc_server.go | 12 ++++++++++-- rpcserver/jsonrpc_server_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/rpcserver/jsonrpc_server.go b/rpcserver/jsonrpc_server.go index 21d597a..472bfa7 100644 --- a/rpcserver/jsonrpc_server.go +++ b/rpcserver/jsonrpc_server.go @@ -146,6 +146,14 @@ func (h *JSONRPCHandler) writeJSONRPCResponse(w http.ResponseWriter, response JS } func (h *JSONRPCHandler) writeJSONRPCError(w http.ResponseWriter, id any, code int, msg string) { + h.writeJSONRPCErrorWithData(w, id, code, msg, nil) +} + +func (h *JSONRPCHandler) writeJSONRPCErrorWithData(w http.ResponseWriter, id any, code int, msg string, data any) { + var dataPtr *any + if data != nil { + dataPtr = &data + } res := JSONRPCResponse{ JSONRPC: "2.0", ID: id, @@ -153,7 +161,7 @@ func (h *JSONRPCHandler) writeJSONRPCError(w http.ResponseWriter, id any, code i Error: &JSONRPCError{ Code: code, Message: msg, - Data: nil, + Data: dataPtr, }, } h.writeJSONRPCResponse(w, res) @@ -324,7 +332,7 @@ func (h *JSONRPCHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { result, err := method.call(ctx, req.Params) if err != nil { if jsonRPCErr, ok := err.(*JSONRPCError); ok { - h.writeJSONRPCError(w, req.ID, jsonRPCErr.Code, jsonRPCErr.Message) + h.writeJSONRPCErrorWithData(w, req.ID, jsonRPCErr.Code, jsonRPCErr.Message, jsonRPCErr.Data) } else { h.writeJSONRPCError(w, req.ID, CodeCustomError, err.Error()) } diff --git a/rpcserver/jsonrpc_server_test.go b/rpcserver/jsonrpc_server_test.go index ac9b5e7..e6bed00 100644 --- a/rpcserver/jsonrpc_server_test.go +++ b/rpcserver/jsonrpc_server_test.go @@ -143,6 +143,33 @@ func TestJSONRPCServerDefaultLiveAndReady(t *testing.T) { require.Equal(t, http.StatusNotFound, rr.Code) } +func TestJSONRPCErrorDataIsPreserved(t *testing.T) { + handlerMethod := func(ctx context.Context, arg int) (int, error) { + errorData := any("some error data") + return 0, &JSONRPCError{ + Code: 1234, + Message: "test error", + Data: &errorData, + } + } + + handler, err := NewJSONRPCHandler(map[string]interface{}{ + "testError": handlerMethod, + }, JSONRPCHandlerOpts{}) + require.NoError(t, err) + + httpServer := httptest.NewServer(handler) + defer httpServer.Close() + + client := rpcclient.NewClient(httpServer.URL) + resp, err := client.Call(context.Background(), "testError", 1) + require.NoError(t, err) + require.NotNil(t, resp.Error) + require.Equal(t, 1234, resp.Error.Code) + require.Equal(t, "test error", resp.Error.Message) + require.Equal(t, "some error data", resp.Error.Data) +} + func TestJSONRPCServerReadyzOK(t *testing.T) { handler := testHandler(JSONRPCHandlerOpts{ ReadyHandler: func(w http.ResponseWriter, r *http.Request) error {