Skip to content

Commit 979642a

Browse files
authored
Add response headers to NylasApiError object (#517)
1 parent 33fff32 commit 979642a

File tree

3 files changed

+65
-8
lines changed

3 files changed

+65
-8
lines changed

lib/nylas/errors.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class JsonParseError < AbstractNylasSdkError; end
1414

1515
# Error class representing a failed response from the Nylas API.
1616
class NylasApiError < AbstractNylasApiError
17-
attr_accessor :type, :request_id, :provider_error, :status_code
17+
attr_accessor :type, :request_id, :provider_error, :status_code, :headers
1818

1919
# Initializes an error and assigns the given attributes to it.
2020
#
@@ -23,24 +23,26 @@ class NylasApiError < AbstractNylasApiError
2323
# @param status_code [Integer] Error status code.
2424
# @param provider_error [Hash, nil] The error from the provider.
2525
# @param request_id [Hash, nil] The ID of the request.
26-
def initialize(type, message, status_code, provider_error = nil, request_id = nil)
26+
def initialize(type, message, status_code, provider_error = nil, request_id = nil, headers = nil)
2727
super(message)
2828
self.type = type
2929
self.status_code = status_code
3030
self.provider_error = provider_error
3131
self.request_id = request_id
32+
self.headers = headers
3233
end
3334

3435
# Parses the error response.
3536
#
3637
# @param response [Hash] Response from the Nylas API.
3738
# @param status_code [Integer] Error status code.
38-
def self.parse_error_response(response, status_code)
39+
def self.parse_error_response(response, status_code, headers = nil)
3940
new(
4041
response["type"],
4142
response["message"],
4243
status_code,
43-
response["provider_error"]
44+
response["provider_error"],
45+
headers
4446
)
4547
end
4648
end

lib/nylas/handler/http_client.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,22 +191,26 @@ def handle_failed_response(http_code, response, path)
191191
def error_hash_to_exception(response, status_code, path)
192192
return if !response || !response.key?(:error)
193193

194+
# Safely get headers without risking KeyError
195+
headers = response.key?(:headers) ? response[:headers] : nil
196+
194197
if %W[#{api_uri}/v3/connect/token #{api_uri}/v3/connect/revoke].include?(path)
195198
NylasOAuthError.new(response[:error], response[:error_description], response[:error_uri],
196199
response[:error_code], status_code)
197200
else
198-
throw_error(response, status_code)
201+
throw_error(response, status_code, headers)
199202
end
200203
end
201204

202-
def throw_error(response, status_code)
205+
def throw_error(response, status_code, headers = nil)
203206
error_obj = response[:error]
204207

205208
# If `error_obj` is just a string, turn it into a hash with default keys.
206209
if error_obj.is_a?(String)
207210
error_obj = {
208211
type: "NylasApiError",
209-
message: error_obj
212+
message: error_obj,
213+
headers: headers
210214
}
211215
end
212216

@@ -217,7 +221,8 @@ def throw_error(response, status_code)
217221
error_obj[:message],
218222
status_code,
219223
provider_error,
220-
response[:request_id]
224+
response[:request_id],
225+
headers
221226
)
222227
end
223228

spec/nylas/handler/http_client_spec.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,31 @@ class TestHttpClient
240240
expect(err_obj.provider_error).to eq("This is the provider error")
241241
expect(err_obj.type).to eq("api_error")
242242
end
243+
244+
it "raises the correct error with headers" do
245+
response = {
246+
request_id: "request-id",
247+
error: {
248+
type: "api_error",
249+
message: "An unexpected error occurred",
250+
provider_error: "This is the provider error"
251+
}
252+
}
253+
headers = {
254+
"x-request-id": "request-id-from-headers",
255+
"x-ratelimit-limit": "100",
256+
"x-ratelimit-remaining": "99"
257+
}
258+
259+
err_obj = http_client.send(:throw_error, response, 400, headers)
260+
261+
expect(err_obj).to be_a(Nylas::NylasApiError)
262+
expect(err_obj.message).to eq("An unexpected error occurred")
263+
expect(err_obj.request_id).to eq("request-id")
264+
expect(err_obj.provider_error).to eq("This is the provider error")
265+
expect(err_obj.type).to eq("api_error")
266+
expect(err_obj.headers).to eq(headers)
267+
end
243268
end
244269

245270
describe "#error_hash_to_exception" do
@@ -293,6 +318,31 @@ class TestHttpClient
293318
expect(err_obj.error_uri).to eq("https://tools.ietf.org/html/rfc6749#section-5.2")
294319
expect(err_obj.error_code).to eq(400)
295320
end
321+
322+
it "raises the correct error with headers" do
323+
response = {
324+
request_id: "request-id",
325+
error: {
326+
type: "api_error",
327+
message: "An unexpected error occurred",
328+
provider_error: "This is the provider error"
329+
},
330+
headers: {
331+
"x-request-id": "request-id-from-headers",
332+
"x-ratelimit-limit": "100",
333+
"x-ratelimit-remaining": "99"
334+
}
335+
}
336+
337+
err_obj = http_client.send(:error_hash_to_exception, response, 400, "https://test.api.nylas.com/foo")
338+
339+
expect(err_obj).to be_a(Nylas::NylasApiError)
340+
expect(err_obj.message).to eq("An unexpected error occurred")
341+
expect(err_obj.request_id).to eq("request-id")
342+
expect(err_obj.provider_error).to eq("This is the provider error")
343+
expect(err_obj.type).to eq("api_error")
344+
expect(err_obj.headers).to eq(response[:headers])
345+
end
296346
end
297347

298348
describe "#handle_failed_response" do

0 commit comments

Comments
 (0)