Skip to content

Commit 45c2b28

Browse files
authored
feat: gracefully handle non json responses (#78)
1 parent 110867d commit 45c2b28

File tree

2 files changed

+64
-30
lines changed

2 files changed

+64
-30
lines changed

lib/resend/request.rb

+15
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ def perform
3434

3535
options[:body] = @body.to_json unless @body.empty?
3636
resp = HTTParty.send(@verb.to_sym, "#{BASE_URL}#{@path}", options)
37+
38+
check_json!(resp)
39+
3740
resp.transform_keys!(&:to_sym) unless resp.body.empty?
3841
handle_error!(resp) if resp[:statusCode] && (resp[:statusCode] != 200 || resp[:statusCode] != 201)
3942
resp
@@ -45,5 +48,17 @@ def handle_error!(resp)
4548
error = Resend::Error::ERRORS[code]
4649
raise(error.new(body, code)) if error
4750
end
51+
52+
private
53+
54+
def check_json!(resp)
55+
if resp.body.is_a?(Hash)
56+
JSON.parse(resp.body.to_json)
57+
else
58+
JSON.parse(resp.body)
59+
end
60+
rescue JSON::ParserError, TypeError
61+
raise Resend::Error::InternalServerError.new("Resend API returned an unexpected response", nil)
62+
end
4863
end
4964
end

spec/request_spec.rb

+49-30
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,58 @@
99
Resend.api_key = "re_123"
1010
end
1111

12-
it "Resend::Error::InvalidRequestError 400" do
13-
req = described_class.new
14-
resp = {
15-
:statusCode => 400,
16-
:message => "400"
17-
}
18-
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::InvalidRequestError, /400/)
19-
end
12+
context '#perform' do
13+
context 'response is not json' do
14+
before do
15+
response = double(HTTParty::Response)
16+
html = "<html>not json</html>"
17+
allow(response).to receive(:body).and_return(html)
18+
allow(HTTParty).to receive(:send).and_return(response)
19+
end
2020

21-
it "Resend::Error::InvalidRequestError 422" do
22-
req = described_class.new
23-
resp = {
24-
:statusCode => 422,
25-
:message => "422"
26-
}
27-
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::InvalidRequestError, /422/)
21+
it 'should be rescuable' do
22+
req = described_class.new
23+
expect { req.perform }.to raise_error(Resend::Error::InternalServerError, /Resend API returned an unexpected response/)
24+
end
25+
end
2826
end
2927

30-
it "Resend::Error::RateLimitExceededError 429" do
31-
req = described_class.new
32-
resp = {
33-
:statusCode => 429,
34-
:message => "429"
35-
}
36-
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::RateLimitExceededError, /429/)
37-
end
28+
context 'handle_error!' do
29+
30+
it "Resend::Error::InvalidRequestError 400" do
31+
req = described_class.new
32+
resp = {
33+
:statusCode => 400,
34+
:message => "400"
35+
}
36+
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::InvalidRequestError, /400/)
37+
end
38+
39+
it "Resend::Error::InvalidRequestError 422" do
40+
req = described_class.new
41+
resp = {
42+
:statusCode => 422,
43+
:message => "422"
44+
}
45+
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::InvalidRequestError, /422/)
46+
end
47+
48+
it "Resend::Error::RateLimitExceededError 429" do
49+
req = described_class.new
50+
resp = {
51+
:statusCode => 429,
52+
:message => "429"
53+
}
54+
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::RateLimitExceededError, /429/)
55+
end
3856

39-
it "Resend::Error::InternalServerError 500" do
40-
req = described_class.new
41-
resp = {
42-
:statusCode => 500,
43-
:message => "500"
44-
}
45-
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::InternalServerError, /500/)
57+
it "Resend::Error::InternalServerError 500" do
58+
req = described_class.new
59+
resp = {
60+
:statusCode => 500,
61+
:message => "500"
62+
}
63+
expect { req.handle_error!(resp) }.to raise_error(Resend::Error::InternalServerError, /500/)
64+
end
4665
end
4766
end

0 commit comments

Comments
 (0)