diff --git a/lib/json_rpc_handler.rb b/lib/json_rpc_handler.rb index 7807429..cde1f2b 100644 --- a/lib/json_rpc_handler.rb +++ b/lib/json_rpc_handler.rb @@ -103,12 +103,26 @@ def process_request(request, &method_finder) success_response id:, result: rescue StandardError => e - error_response id:, error: { - code: ErrorCode::InternalError, - message: 'Internal error', - data: e.message, - } + handle_error e, id + end + end + + def handle_error(error, id) + raw_code = error.respond_to?(:code) ? error.code : nil + + code, message = case raw_code + when ErrorCode::InvalidRequest then [ErrorCode::InvalidRequest, 'Invalid Request'] + when ErrorCode::InvalidParams then [ErrorCode::InvalidParams, 'Invalid params'] + when ErrorCode::ParseError then [ErrorCode::ParseError, 'Parse error'] + when ErrorCode::InternalError then [ErrorCode::InternalError, 'Internal error'] + else [ErrorCode::InternalError, 'Internal error'] end + + error_response id:, error: { + code:, + message:, + data: error.message, + } end def valid_version?(version) diff --git a/test/json_rpc_handler_test.rb b/test/json_rpc_handler_test.rb index 83b70ca..5e8ca89 100644 --- a/test/json_rpc_handler_test.rb +++ b/test/json_rpc_handler_test.rb @@ -2,6 +2,15 @@ require 'test_helper' +class RequestHandlerError < StandardError + attr_reader :code + + def initialize(message, request = {}, code: nil, **_options) + super(message) + @code = code + end +end + describe JsonRpcHandler do before do @registry = {} @@ -454,7 +463,93 @@ it "returns an error with the id set to nil when the request is invalid" do handle_json({ jsonrpc: "0.0", id: 1, method: "add", params: { a: 1, b: 2 } }.to_json) - assert_nil @response[:id] + assert_nil @response[:id] + end + + describe 'handle_error' do + it "returns an error object as a Invalid request error when an exception with `-32602` code is raised" do + register "logging/setLevel" do |params| + raise RequestHandlerError.new("Invalid log level", {}, code: -32602) + end + + handle_json({ jsonrpc: "2.0", id: 1, method: "logging/setLevel", params: { level: "info" } }.to_json) + + assert_rpc_error expected_error: { + code: -32602, + message: 'Invalid params', + data: 'Invalid log level', + } + end + + it "returns an error object as a Invalid request error when an exception with `-32600` code is raised" do + register "logging/setLevel" do |params| + raise RequestHandlerError.new("Invalid log level", {}, code: -32600) + end + + handle_json({ jsonrpc: "2.0", id: 1, method: "logging/setLevel", params: { level: "info" } }.to_json) + + assert_rpc_error expected_error: { + code: -32600, + message: 'Invalid Request', + data: 'Invalid log level', + } + end + + it "returns an error object as a Parse error when an exception with `-32700` code is raised" do + register "logging/setLevel" do |params| + raise RequestHandlerError.new("Invalid log level", {}, code: -32700) + end + + handle_json({ jsonrpc: "2.0", id: 1, method: "logging/setLevel", params: { level: "info" } }.to_json) + + assert_rpc_error expected_error: { + code: -32700, + message: 'Parse error', + data: 'Invalid log level', + } + end + + it "returns an error object as a Internal error when an exception with undefined code is raised" do + register "logging/setLevel" do |params| + raise RequestHandlerError.new("Invalid log level", {}, code: -99999) + end + + handle_json({ jsonrpc: "2.0", id: 1, method: "logging/setLevel", params: { level: "info" } }.to_json) + + assert_rpc_error expected_error: { + code: -32603, + message: 'Internal error', + data: 'Invalid log level', + } + end + + it "returns an error object as a Internal error when an exception with nil code is raised" do + register "logging/setLevel" do |params| + raise RequestHandlerError.new("Invalid log level", {}, code: nil) + end + + handle_json({ jsonrpc: "2.0", id: 1, method: "logging/setLevel", params: { level: "info" } }.to_json) + + assert_rpc_error expected_error: { + code: -32603, + message: 'Internal error', + data: 'Invalid log level', + } + end + + it "returns an error object as a internal error when an exception without code is raised" do + register "logging/setLevel" do |params| + raise RequestHandlerError.new("Invalid log level", {}, error_type: :invalid_log_level) + end + + handle_json({ jsonrpc: "2.0", id: 1, method: "logging/setLevel", params: { level: "info" } }.to_json) + + assert_rpc_error expected_error: { + code: -32603, + message: 'Internal error', + data: 'Invalid log level', + } + end end end