tpow
tpow

Reputation: 7894

How to handle exceptions with Ruby Rest-Client

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...?

Upvotes: 41

Views: 53537

Answers (6)

wich
wich

Reputation: 17157

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

Upvotes: 62

Chamith Jayaweera
Chamith Jayaweera

Reputation: 13

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

Upvotes: 1

Akash Kinwad
Akash Kinwad

Reputation: 815

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
}

Upvotes: -2

Raphael
Raphael

Reputation: 1721

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.

Upvotes: 27

MegaTux
MegaTux

Reputation: 1651

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

Upvotes: 1

Serhiy Nazarov
Serhiy Nazarov

Reputation: 379

rescue RestClient::ExceptionWithResponse => err

Upvotes: 5

Related Questions