Skip to content

Commit

Permalink
JSON parse bodies sent to metadata to get keyword filtering for free (#…
Browse files Browse the repository at this point in the history
…13)

* JSON parse bodies sent to metadata to get keyword filtering for free

* Handle nil body
  • Loading branch information
Michal Krzywinski authored Dec 15, 2020
1 parent b72a288 commit b927821
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 14 deletions.
10 changes: 8 additions & 2 deletions lib/restful_resource_bugsnag/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ def call(notification)
if exception.is_a?(RestfulResource::HttpClient::HttpError)
notification.add_tab(:restful_resource_response, {
status: exception.response.status,
body: exception.response.body,
body: attempt_json_parse(exception.response.body),
headers: exception.response.headers
})
notification.add_tab(:restful_resource_request, {
method: exception.request.method,
url: exception.request.url,
body: exception.request.body
body: attempt_json_parse(exception.request.body)
})
end

Expand Down Expand Up @@ -47,5 +47,11 @@ def call(notification)
def request_host_from_exception(exception)
URI.parse(exception.request.url).host
end

def attempt_json_parse(string)
JSON.parse(string)
rescue JSON::ParserError, TypeError
string
end
end
end
87 changes: 75 additions & 12 deletions spec/restful_resource_bugsnag_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
it { is_expected.to_not be_nil }
it { is_expected.to include("status" => error.response.status) }
it { is_expected.to include("headers" => error.response.headers) }
it { is_expected.to include("body" => error.response.body) }
it { is_expected.to include("body" => JSON.parse(error.response.body)) }
end

describe 'request tab' do
Expand All @@ -25,6 +25,24 @@
it { is_expected.to_not be_nil }
it { is_expected.to include("method" => error.request.method.to_s) }
it { is_expected.to include("url" => error.request.url) }
it { is_expected.to include("body" => JSON.parse(error.request.body)) }
end
end

shared_examples 'passes unparsed body to bugsnag' do
before do
Bugsnag.notify(error)
end

describe 'response tab' do
subject(:response_tab) { get_tab(sent_notification, 'restful_resource_response') }

it { is_expected.to include("body" => error.response.body) }
end

describe 'request tab' do
subject(:request_tab) { get_tab(sent_notification, 'restful_resource_request') }

it { is_expected.to include("body" => error.request.body) }
end
end
Expand All @@ -46,53 +64,98 @@
end

describe 'when a notification is sent for an UnprocessableEntity error' do
let(:request_body) { '{"msg": "The request body"}' }
let(:response_body) { '{"msg": "a body"}' }
let(:response) do
{
:status => 422,
:headers => {
"content-type" => "text/html; charset=utf-8",
"content-length" => "6"
},
:body => "a body"
:body => response_body
}
end
let(:error) { make_error(RestfulResource::HttpClient::UnprocessableEntity, response, request_body: request_body) }

it_behaves_like RestfulResourceBugsnag do
let(:error) { make_error(RestfulResource::HttpClient::UnprocessableEntity, response) }
it_behaves_like RestfulResourceBugsnag

context 'message body is not valid JSON' do
it_behaves_like 'passes unparsed body to bugsnag' do
let(:response_body) { 'a body' }
let(:request_body) { 'The request body' }
end
end

context 'message body is nil' do
it_behaves_like 'passes unparsed body to bugsnag' do
let(:response_body) { nil }
let(:request_body) { nil }
end
end
end

describe 'when a notification is sent for an OtherHttpError error' do
let(:request_body) { '{"msg": "The request body"}' }
let(:response_body) { '{"msg": "Server Error"}' }
let(:response) do
{
:status => 500,
:headers => {
"content-type" => "text/html; charset=utf-8",
"content-length" => "19"
},
:body => "Server Error"
:body => response_body
}
end
let(:error) { make_error(RestfulResource::HttpClient::OtherHttpError, response, request_body: request_body) }

it_behaves_like RestfulResourceBugsnag do
let(:error) { make_error(RestfulResource::HttpClient::OtherHttpError, response) }
it_behaves_like RestfulResourceBugsnag

context 'message body is not valid JSON' do
it_behaves_like 'passes unparsed body to bugsnag' do
let(:response_body) { 'Server Error' }
let(:request_body) { 'The request body' }
end
end

context 'message body is nil' do
it_behaves_like 'passes unparsed body to bugsnag' do
let(:response_body) { nil }
let(:request_body) { nil }
end
end
end

describe 'when a notification is sent for an ServiceUnavailable error' do
let(:request_body) { '{"msg": "The request body"}' }
let(:response_body) { '{"msg": "Service Unavailable"}' }
let(:response) do
{
:status => 503,
:headers => {
"content-type" => "text/html; charset=utf-8",
"content-length" => "19"
},
:body => "Service Unavailable"
:body => response_body
}
end
let(:error) { make_error(RestfulResource::HttpClient::ServiceUnavailable, response, request_body: request_body) }

it_behaves_like RestfulResourceBugsnag do
let(:error) { make_error(RestfulResource::HttpClient::ServiceUnavailable, response) }
it_behaves_like RestfulResourceBugsnag

context 'message body is not valid JSON' do
it_behaves_like 'passes unparsed body to bugsnag' do
let(:response_body) { 'Service Unavailable' }
let(:request_body) { 'The request body' }
end
end

context 'message body is nil' do
it_behaves_like 'passes unparsed body to bugsnag' do
let(:response_body) { nil }
let(:request_body) { nil }
end
end

describe 'grouping ServiceUnavailable errors' do
Expand Down Expand Up @@ -153,14 +216,14 @@

# this is some what convoluted in order to recreate how
# errors are sent in a real app using RestfulResource
def make_error(type, response, url: 'http://example.com')
def make_error(type, response, url: 'http://example.com', request_body: '{"msg": "The request body"}')
error = nil

begin
begin
raise Faraday::ClientError, "The original error"
rescue Faraday::ClientError => e
request = RestfulResource::Request.new(:get, url, body: "The request body")
request = RestfulResource::Request.new(:get, url, body: request_body)
raise type.new(request, response)
end
rescue Exception => e
Expand Down

0 comments on commit b927821

Please sign in to comment.