Skip to content

Commit

Permalink
Fix rescue_from ValidationErrors exception
Browse files Browse the repository at this point in the history
  • Loading branch information
numbata committed Jul 23, 2024
1 parent fb67ea9 commit a8925b0
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
17 changes: 13 additions & 4 deletions lib/grape/error_formatter/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ class << self
def call(message, backtrace, options = {}, env = nil, original_exception = nil)
result = wrap_message(present(message, env))

rescue_options = options[:rescue_options] || {}
result = result.merge(backtrace: backtrace) if rescue_options[:backtrace] && backtrace && !backtrace.empty?
result = result.merge(original_exception: original_exception.inspect) if rescue_options[:original_exception] && original_exception
result = merge_rescue_options(result, backtrace, options, original_exception) if result.is_a?(Hash)

::Grape::Json.dump(result)
end

private

def wrap_message(message)
if message.is_a?(Exceptions::ValidationErrors) || message.is_a?(Hash)
if message.is_a?(Hash)
message
elsif message.is_a?(Exceptions::ValidationErrors)
message.as_json
else
{ error: ensure_utf8(message) }
end
Expand All @@ -30,6 +31,14 @@ def ensure_utf8(message)

message.encode('UTF-8', invalid: :replace, undef: :replace)
end

def merge_rescue_options(result, backtrace, options, original_exception)
rescue_options = options[:rescue_options] || {}
result = result.merge(backtrace: backtrace) if rescue_options[:backtrace] && backtrace && !backtrace.empty?
result = result.merge(original_exception: original_exception.inspect) if rescue_options[:original_exception] && original_exception

result
end
end
end
end
Expand Down
51 changes: 51 additions & 0 deletions spec/grape/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2743,6 +2743,57 @@ def self.call(message, _backtrace, _options, _env, _original_exception)
it { is_expected.to have_key('backtrace') & have_key('original-exception') }
end
end

context 'when rescue validation errors include backtrace and original exception' do
let(:app) do
response_type = response_format

Class.new(Grape::API) do
format response_type

rescue_from Grape::Exceptions::ValidationErrors, backtrace: true, original_exception: true do |e|
error!(e, 418, {}, e.backtrace, e)
end

params do
requires :weather
end
get '/forecast' do
'sunny'
end
end
end

before do
get '/forecast'
end

context 'with json response type format' do
subject { JSON.parse(last_response.body) }

let(:response_format) { :json }

it 'does not include backtrace or original exception' do
expect(subject).to match([{ 'messages' => ['is missing'], 'params' => ['weather'] }])
end
end

context 'with txt response type format' do
subject { last_response.body }

let(:response_format) { :txt }

it { is_expected.to include('backtrace', 'original exception') }
end

context 'with xml response type format' do
subject { Grape::Xml.parse(last_response.body)['error'] }

let(:response_format) { :xml }

it { is_expected.to have_key('backtrace') & have_key('original-exception') }
end
end
end

describe '.content_type' do
Expand Down

0 comments on commit a8925b0

Please sign in to comment.