How to handle exceptions with Ruby Rest-Client
Asked Answered
C

6

41

I recently switched from Ruby's Net:HTTP class to rest-client 1.6.7.

I find it a lot easier to form requests, but unlike Net:HTTP request, when rest-client gets anything other than a 200, the request dies. I've tried putting a breakpoint directly after the RestClient.get, and it never gets hit - so I'm doing something wrong.

def get_member_using_card
  resource = "#{@settings_app_uri}api/v1/card/#{self.member_card_num}?token=#{@settings.api_key}"
  response = RestClient.get resource
  if response.code == 200 
    card = JSON.parse(response.body)
    self.customer_id = card['card']['customer_id']
  else
    return 0
  end
end

Which results in this stacktrace:

RestClient::ResourceNotFound - 404 Resource Not Found:
        /Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/abstr
act_response.rb:48:in `return!'
        /Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:230:in `process_result'
        /Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:178:in `block in transmit'
        /Users/tim/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/http.rb:627:in `start'
        /Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:172:in `transmit'
        /Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:64:in `execute'
        /Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:33:in `execute'
        /Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient.rb:68
:in `get'

Can someone tell me how to properly evaluate the response code and keep this exception from happening...?

Crowbar answered 10/7, 2012 at 22:38 Comment(0)
O
62

See heading Exceptions on http://rubydoc.info/gems/rest-client/

  • for results code between 200 and 207 a RestClient::Response will be returned
  • for results code 301, 302 or 307 the redirection will be followed if the request is a get or a head
  • for result code 303 the redirection will be followed and the request transformed into a get
  • for other cases a RestClient::Exception holding the Response will be raised, a specific exception class will be thrown for know error codes

RestClient.get 'http://example.com/resource'
➔ RestClient::ResourceNotFound: RestClient::ResourceNotFound`

begin
  RestClient.get 'http://example.com/resource'
rescue RestClient::ExceptionWithResponse => e
  e.response
end
➔ 404 Resource Not Found | text/html 282 bytes
Otter answered 17/10, 2012 at 9:4 Comment(0)
E
27

Also in the same documentation @wich pointed to, you can pass a block to RestClient.get such that it will not throw an exception on non-200 response codes:

# Don't raise exceptions but return the response
RestClient.get('http://example.com/resource'){|response, request, result| response }

See the "Result Handling" section from the documentation.

Evvie answered 22/2, 2013 at 15:50 Comment(0)
I
5
rescue RestClient::ExceptionWithResponse => err
Intercostal answered 10/8, 2016 at 13:18 Comment(0)
F
1

There are several errors that could happen, specific exception types like Errno::EHOSTUNREACH or the more generic ExceptionWithResponse. Check the readme for more info.

Falla answered 31/8, 2018 at 20:26 Comment(0)
H
1

I believe the best way to handle exceptions of an API client is to get the original error message thrown by the API endpoint. Here is an example code to handle that with RestClient

require 'json'

def get_call
    begin
        standard_response = {body: nil, success: false, message: ''}

        response = RestClient.get('https://example.com/api/v1/xx', headers={'Authorization' => 'AbcDef xxx'})

        standard_response[:success] = true
        standard_response[:body] = JSON.parse(response.body)
    rescue RestClient::ExceptionWithResponse => e
        http_body = JSON.parse(e.http_body) # This is the original response from the API endpoint. e.g. {'message': 'Reason for the failure'}
        meaningful_error_message = http_body['message'].nil? ? e.message : http_body['message'] # if {'message': 'error message'} is the format of your API
        standard_response[:message] = meaningful_error_message
    end
    
    standard_response
end
Henrion answered 15/8, 2022 at 9:24 Comment(0)
H
-2

Beautiful way to handle the exceptions in rest client.

For more info do check rest-client#response-callbacks-error-handling

RestClient.get('http://example.com/resource') { |response, request, result, &block|
  case response.code
  when 200
    p "It worked !"
    response
  when 423
    raise SomeCustomExceptionIfYouWant
  else
    response.return!(&block)
  end
}
Hyderabad answered 29/4, 2021 at 2:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.