From 25f4b4a868be2a02971f4604d134b5f105459923 Mon Sep 17 00:00:00 2001 From: Abe Tomoaki Date: Wed, 16 Oct 2024 09:28:11 +0900 Subject: [PATCH] response: parse: Include input JSON in Error, on JSON parsing errors (#32) For example, when the input is `["header", :{"return_code":-77}}`, a parse error. The error is then as follows. ``` `parse': unexpected token at ':{"return_code":-77}}' (JSON::ParserError) ``` Include the input JSON in the error since the error does not include the full input JSON, making it difficult to debug. --------- Co-authored-by: Sutou Kouhei --- lib/groonga/client/error.rb | 30 +++++++++++++++++++++++++++++ lib/groonga/client/request/error.rb | 20 +++---------------- lib/groonga/client/response/base.rb | 11 +++++++++-- test/response/test-base.rb | 15 +++++++++++++++ 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/lib/groonga/client/error.rb b/lib/groonga/client/error.rb index 6ec96d8..0f5ebfd 100644 --- a/lib/groonga/client/error.rb +++ b/lib/groonga/client/error.rb @@ -18,5 +18,35 @@ module Groonga class Client class Error < StandardError end + + class ErrorResponse < Error + attr_reader :response + def initialize(response) + @response = response + command = @response.command + status_code = @response.status_code + error_message = @response.error_message + message = "failed to execute: " + message << "#{command.command_name}: #{status_code}: " + message << "<#{error_message}>: " + message << command.to_command_format + super(message) + end + end + + class InvalidResponse < Error + attr_reader :command + attr_reader :raw_response + def initialize(command, raw_response, error_message) + @command = command + @raw_response = raw_response + message = +"invalid response: " + message << "#{command.command_name}: " + message << "#{error_message}: " + message << "<#{command.to_command_format}>: " + message << "<#{raw_response}>" + super(message) + end + end end end diff --git a/lib/groonga/client/request/error.rb b/lib/groonga/client/request/error.rb index e7ffb16..e7678ed 100644 --- a/lib/groonga/client/request/error.rb +++ b/lib/groonga/client/request/error.rb @@ -19,23 +19,9 @@ module Groonga class Client module Request - class Error < Client::Error - end - - class ErrorResponse < Error - attr_reader :response - def initialize(response) - @response = response - command = @response.command - status_code = @response.status_code - error_message = @response.error_message - message = "failed to execute: " - message << "#{command.command_name}: #{status_code}: " - message << "<#{error_message}>: " - message << command.to_command_format - super(message) - end - end + # For backward compatibility + Error = Client::Error + ErrorResponse = Client::ErrorResponse end end end diff --git a/lib/groonga/client/response/base.rb b/lib/groonga/client/response/base.rb index 2bb8f19..696195f 100644 --- a/lib/groonga/client/response/base.rb +++ b/lib/groonga/client/response/base.rb @@ -73,9 +73,16 @@ def parse(command, raw_response) callback = command["callback"] if callback and /\A#{Regexp.escape(callback)}\((.+)\);\z/ =~ raw_response - response = JSON.parse($1) + json = $1 else - response = JSON.parse(raw_response) + json = raw_response + end + begin + response = JSON.parse(json) + rescue JSON::ParserError => error + raise InvalidResponse.new(command, + raw_response, + "invalid JSON: #{error}") end if response.is_a?(::Array) header, body = response diff --git a/test/response/test-base.rb b/test/response/test-base.rb index 8d544f4..623a758 100644 --- a/test/response/test-base.rb +++ b/test/response/test-base.rb @@ -222,5 +222,20 @@ def test_jsonp response = Groonga::Client::Response::Base.parse(command, raw_response) assert_equal(1396012478, response.body["start_time"]) end + + def test_invalid_json + command = Groonga::Command::Base.new("cancel") + raw_response = '["header", :{"return_code":-77}}' + begin + JSON.parse(raw_response) + rescue JSON::ParserError => error + parse_error_message = "invalid JSON: #{error}" + end + error = Groonga::Client::InvalidResponse.new(command, raw_response, parse_error_message) + + assert_raise(error) do + Groonga::Client::Response::Base.parse(command, raw_response) + end + end end end